我有一个相当简单的表单,但是我收到了一个带有ModelChoiceField的TypeError,我无法理解为什么。表单返回模型ID号,并且使用该号码我应该能够查找特定模型并将其用于任何目的。虽然这不是那样的。这是我的表格代码:
class TestimonialForm(forms.Form):
title = forms.CharField(max_length=100)
content = forms.CharField(max_length=500, widget=forms.Textarea)
ratings = (
(1, '1'),
(2, '2'),
(3, '3'),
(4, '4'),
(5, '5')
)
rating = forms.ChoiceField(choices=ratings, widget=forms.RadioSelect)
reward = forms.ModelChoiceField(queryset=Reward.objects.all())
username = forms.CharField(max_length=50, widget=forms.HiddenInput)
def clean(self):
cleaned_data = super(TestimonialForm, self).clean()
usr = cleaned_data.get('username')
res = cleaned_data.get('reward')
if Reward_Review.objects.filter(id=res.id).filter(affiliate__username=usr):
raise forms.ValidationError("You have already submitted a testimonial. You can only submit one per gift card.")
if not Redeem.objects.filter(reward__id=res.id).filter(affiliate__username=usr):
raise forms.ValidationError("You haven't received this gift card yet, so you cannot write a review for it.")
def clean_username(self):
data = self.cleaned_data['username']
try:
Affiliate.objects.get(user__username=data)
except ObjectDoesNotExist, e:
msg = 'The username provided by the form submission does not match anyone in our database.'
logger.exception(e)
logger.debug(msg, exc_info=True)
raise forms.ValidationError("Invalid username. Please try again later.")
return data
def save(self, request, *args, **kwargs):
data = self.cleaned_data
user = request.user
re = Reward.objects.get(id=data['reward'])
points = Points.objects.create(affiliate=user, points=float(10), from_offer=False, from_task=True)
rate = Reward_Rating.objects.create(affiliate=user, reward=re, rating_value=data['rating'])
testimonial = Reward_Review.objects.create(affiliate=user, reward=re, reward_rating=rate, review_title=data['title'], review_content=data['content'])
return testimonial
完整追踪:
Environment:
Request Method: POST
Traceback:
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
114. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/views/generic/base.py" in view
69. return self.dispatch(request, *args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
29. return bound_func(*args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
22. return view_func(request, *args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
25. return func(self, *args2, **kwargs2)
File "/app/myapp/views.py" in dispatch
756. return super(TestimonialFormView, self).dispatch(*args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/newrelic-2.8.0.7/newrelic/hooks/framework_django.py" in wrapper
809. return wrapped(*args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
87. return handler(request, *args, **kwargs)
File "/app/.heroku/python/lib/python2.7/site-packages/django/views/generic/edit.py" in post
171. return self.form_valid(form)
File "/app/myapp/views.py" in form_valid
743. form.save(self.request)
File "/app/myapp/forms.py" in save
215. re = Reward.objects.get(id=data['reward'])
Exception Type: TypeError at /testimonials/
Exception Value: 'NoneType' object has no attribute '__getitem__'
答案 0 :(得分:2)
Form
源代码中的Somewhere有一行:
self.cleaned_data = self.clean()
这意味着您应该使用clean
方法返回字典。
这样的事情:
def clean(self, ...):
// whatever
return cleaned_data
注意:在django的未来版本中不需要从clean
方法返回字典:
在Django开发版中更改:在以前版本的Django中, form.clean()需要返回cleaning_data的字典。这个 方法仍然可以返回要使用的数据字典,但它不是 需要更长时间。
答案 1 :(得分:1)
Form.clean()
必须返回已清理的数据。
答案 2 :(得分:0)
Probaby问题就在这里
re = Reward.objects.get(id=data['reward'])
使用ModelChoiceField
时,您的cleaned_data
词典已经包含相应的对象(而不是id
) - 所以只需
re = data['reward']