django 表单和 __init__ 函数:意外的关键字参数 'user'

django forms and __init__ function: unexpected keyword argument 'user'

我参加了 kenneth love 速成课程,但遇到无法解决的意外错误:

"init() 得到了意外的关键字参数 'user'"

这里是表格 class:

class TalkTalkListForm(forms.ModelForm):
    class Meta:
        model = models.Talk
        fields = ('talk_list',)

    def __init__(self, *args, **kwargs):
        super(TalkTalkListForm, self).__init__(*args, **kwargs)
        self.fields['talk_list'].queryset = (
            self.instance.talk_list.user.lists.all())

        self.helper = FormHelper()
        self.helper.layout = Layout(
            'talk_list',
            ButtonHolder(
                Submit('move', 'Move', css_class='btn-primary')
            )
        )

这里是 Talk 模型:

class Talk(models.Model):
    ROOM_CHOICES = (
            ('BS1_O', 'BS1_O'),
            ('BS1TC', 'BS1TC'),
            ('BS3_O', 'BS3_O'),
            ('BS3TC', 'BS3TC'),
    )
    talk_list = models.ForeignKey(TalkList, related_name='talks')
    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, blank=True)
    when = models.DateTimeField()
    room = models.CharField(max_length=5, choices=ROOM_CHOICES)
    host = models.CharField(max_length=255)
    talk_rating = models.IntegerField(blank=True, default=0)
    speaker_rating = models.IntegerField(blank=True, default=0)   

    notes = models.TextField(blank=True, default='')
    notes_html = models.TextField(blank=True, default='', editable=False)

    class Meta:
        ordering = ('when', 'room')
        unique_together = ('talk_list', 'name')

    def __unicode__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        self.notes_html = mistune.markdown(self.notes)
        super(Talk, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('talks:talks:detail', kwargs={'slug': self.slug})       

    @property
    def overall_rating(self):
        if self.talk_rating and self.speaker_rating:
            return (self.talk_rating + self.speaker_rating) / 2
        return 0  

我可以看到 Talk 没有属性 'user' 但我以某种方式将 'user' 属性传递给 init。这是问题的原因吗?

我知道 kwargs 是命名参数,所以一个不期望的命名参数会抛出一个错误,但我不知道如何摆脱这个错误。

更新:

class TalkDetailView(views.LoginRequiredMixin, generic.DetailView):
    http_method_names = ['get', 'post']
    model = models.Talk

    def get_queryset(self):
        return self.model.objects.filter(talk_list__user=self.request.user)

    def get_context_data(self, **kwargs):
        context = super(TalkDetailView, self).get_context_data(**kwargs)
        obj = context['object']
        rating_form = forms.TalkRatingForm(self.request.POST or None,instance=obj)

        list_form = forms.TalkTalkListForm(self.request.POST or None,instance=obj)        

        context.update({
            'rating_form': rating_form,
            'list_form': list_form
        })
        return context

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        if 'save' in request.POST:
            talk_form = forms.TalkRatingForm(request.POST or None,
                                             instance=self.object)
            if talk_form.is_valid():
                talk_form.save()

        if 'move' in request.POST:
            list_form = forms.TalkTalkListForm(request.POST or None,
                                               instance=self.object,
                                               user=request.user)
            if list_form.is_valid():
                list_form.save()

        return redirect(self.object)

我不明白为什么你把 request.user 放在 init 中,如果你已经通过 request.user == return self.model.objects.filter(talk_list__user=self.request.user)

过滤了查询集

总之...

1) 如果你想以 __init__ 的形式访问 kwarg,你应该在调用 super...

之前 pop
def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', False)
    # now you have removed it from kwargs and `super` call will work as expected
    super(TalkTalkListForm, self).__init__(*args, **kwargs)
    # do smth with `user`

2) 如果你想将 request.user 保存到对象中,请在你的视图中执行以下操作:

if list_form.is_valid():
    obj = list_form.save()
    obj.talk_list.user = request.user
    obj.save()