我有这样的形式:
class ServiceTargetForm(forms.ModelForm):
class Meta:
model = ServiceTarget
fields=('target_type', 'target_value', 'target_threshold')
所有字段都是必需的 .
为了使一切变得更复杂,这个模型具有unique_together条件:
class ServiceTarget(models.Model):
service = models.ForeignKey(Service, verbose_name = _(u"Service"))
all the other fields
...
class Meta:
ordering = ['service__car__name', 'service__car__reg_no','service__name',]
verbose_name = _(u"Service target")
verbose_name_plural = _(u"Service targets")
unique_together = ("service__id", "target_type")
所以保存这样的空表:
ServiceTargetFormSet = inlineformset_factory(Service, ServiceTarget, extra = 1, form = ServiceTargetForm, formset = MyInlineFormSet)
if request.method == 'POST':
form = ServiceForm(request.POST, cars_queryset = cars_queryset, client = account)
if form.is_valid():
new_service = form.save(commit = False)
stformset = ServiceTargetFormSet(request.POST, instance = new_service)
if stformset.is_valid():
form.save()
stformset.save()
messages.success(request, ugettext(u"New service was successfully created."))
redirect_to = '/services/'
return HttpResponseRedirect(request, redirect_to)
else:
messages.error(request, ugettext(u"Creating new service failed"))
应该捍卫失败 - 但不是 . 发布的Queryset是:
<QueryDict: {u'servicetarget_set-0-target_value': [u''], u'servicetarget_set-INITIAL_FORMS': [u'0'], u'name': [u'asdasd2q31'], u'recipients': [u'4'], u'car': [u'22'], u'message_delivery_method': [u'email'], u'servicetarget_set-0-target_threshold': [u''], u'servicetarget_set-TOTAL_FORMS': [u'2'], u'more-rows-count': [u'0'], u'servicetarget_set-0-target_type': [u'km'], u'servicetarget_set-1-target_type': [u'km'], u'csrfmiddlewaretoken': [u'blablabla'], u'servicetarget_set-1-target_value': [u''], u'servicetarget_set-MAX_NUM_FORMS': [u''], u'message': [u'asdasdasd'], u'servicetarget_set-1-target_threshold': [u'']}>
即使所有重要的字段都是空的,它也会很干净:[u''] . 所以人们会认为如果它有效 - 它也可以成功地保存......但事实并非如此 . 在数据库中找不到记录 . 除了由表单创建的记录 - 验证和保存就好了 .
更新:发现类似的问题,也没有答案,似乎是完全相同的问题:Make inlineformset in django required
我为自己创建了testscript以在shell中使用,它会带来所有相同的结果:
q = 'servicetarget_set-0-target_value=&servicetarget_set-INITIAL_FORMS=0&servicetarget_set-0-id=&name=asdasdasd&recipients=4&car=13&servicetarget_set-1-target_type=km&servicetarget_set-1-service=&servicetarget_set-0-target_threshold=&servicetarget_set-TOTAL_FORMS=2&servicetarget_set-0-service=&servicetarget_set-1-target_threshold=&more-rows-count=0&servicetarget_set-0-target_type=km&servicetarget_set-1-id=&csrfmiddlewaretoken=90018471df61d327b6288cb38ad15630&servicetarget_set-1-target_value=&servicetarget_set-MAX_NUM_FORMS=&message=asdasdasd&message_delivery_method=email'
from django.http import QueryDict
qd = QueryDict(q)
from account.models import Account
account = Account.objects.get(id = 2)
from services.models import Service, ServiceTarget
from services.forms import ServiceTargetForm, MyInlineFormSet, ServiceForm
from django.contrib.auth.models import User
u = User.objects.get(id = 5)
from guardian.shortcuts import get_objects_for_user
cars_queryset = get_objects_for_user(u, 'cars.can_access_car').order_by('reg_no').filter(client = account)
form = ServiceForm(qd, cars_queryset = cars_queryset, client = account)
form.is_valid()
True
new_service = form.save(commit = False)
from django.forms.models import inlineformset_factory
ServiceTargetFormSet = inlineformset_factory(Service, ServiceTarget, fk_name="service", extra = 1, form = ServiceTargetForm, formset = MyInlineFormSet)
stformset = ServiceTargetFormSet(qd, instance = new_service)
stformset.is_valid()
True
stformset.cleaned_data
[{}, {}]
stformset.errors
[{}, {}]
stformset.non_form_errors()
[]
Update2:Django formsets: make first required?接受回答这里说为什么不提出错误 - 显然形式必须将empty_permited设置为False .
1 回答
它与此不完全相同:
Django formsets: make first required?
但这里的答案也适用于此 .
如果formsets表格类没有将empty_permitted参数设置为False,则空表单将通过验证 .
因此,您可以通过以下两种方式之一解决此问题:
他们在我添加的链接中这样做的方式
在formsets中做同样的事情,形成类
__init__
方法 .