同样的问题让我很困惑,非常感谢 aumo 和 Vinayak 的回答给了我很大的启发!
作为一个初学者,我总是尝试直接使用“模型+基于类的视图+模板”结构来避免我的应用程序失控。
在 CBV 中重写 form_valid 函数的行为相同(由 Vinayak 回答),通过自定义 Mixin 类来封装函数可能看起来更好。我的代码 asf(基于 django 2.0 版):
# models.py
class Incident(models.Model):
numboys = models.SmallIntegerField(default=0)
numgirls = models.SmallIntegerField(default=0)
classttl = models.SmallIntegerField(default=0)
# views.py
def retunTestPassedResp(request):
return HttpResponse()
class NumValidationMixin:
def form_valid(self, form):
data = self.request.POST
boys = data.get('numboys')
girls = data.get('numgirls')
ttl = data.get('classttl')
if boys and girls and ttl:
if int(ttl) == int(boys) + int(girls):
return super().form_valid(form)
# use form.errors to add the error msg as a dictonary
form.errors['input invalid'] = '%s + %s not equal %s'%(boys, girls, ttl)
form.errors['input invalid'] = 'losing input with boys or other'
return self.form_invalid(form)
class UpdateIncident(NumValidationMixin, UpdateView):
model = Incident
fields = ['numboys', 'numgirls', 'classttl']
success_url = reverse_lazy('test-passed')
# templates/.../Incident_form.html
[...]
<body>
{{form}}
{% if form.errors %}
<p>get error</p>
{{form.errors}}
{% endif %}
</body>
我也做了一个单元测试,通过了。
# tests.py
class IncidentUpdateTest(TestCase):
def setUp(self):
Incident.objects.create()
def test_can_update_with_right_data(self):
[...]
def test_invalid_error_with_illegal_post(self):
response = self.client.post(
reverse('update-incident', args=(1,)),
data={'numboys': '1', 'numgirls': '1', 'classttl': '3'}
)
self.assertEqual(Incident.objects.first().classttl, 0)
# testing response page showing error msg
self.assertContains(response, 'not equal')
更准确的代码示例和解释,请在django document找到。
希望这个回答对和我一样的初学者和自学朋友有所帮助。