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()
我参加了 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()