我使用modelformset_factory,并使用full_clean()来验证具有unique_together = True的表单。我想知道在unique_together不验证的情况下处理错误的最佳方法是什么,以便在模板中返回错误消息。
请查看我的观点,并告诉我,如果我改变了我的方式,或者是否有更好的方法。
模型:
class Attribute(models.Model):
shapefile = models.ForeignKey(Shapefile)
name = models.CharField(max_length=255, db_index=True)
type = models.IntegerField()
width = models.IntegerField()
precision = models.IntegerField()
def __unicode__(self):
return self.name
def delete(self):
shapefile = self.shapefile
feature_selected = Feature.objectshstore.filter(shapefile=shapefile)
feature_selected.hremove('attribute_value', self.name)
super(Attribute, self).delete()
class Meta:
unique_together = (('name', 'shapefile'),)
形式:
class AttributeForm(ModelForm):
def __init__(self, *args, **kwargs):
super(AttributeForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.pk:
self.fields['type'].widget.attrs['disabled'] = True
self.fields['type'].required = False
self.fields['width'].widget.attrs['readonly'] = True
self.fields['precision'].widget.attrs['readonly'] = True
def clean_type(self):
if self.instance and self.instance.pk:
return self.instance.type
else:
return self.cleaned_data['type']
type = forms.ChoiceField(choices=FIELD_TYPE)
class Meta:
model = Attribute
exclude = 'shapefile'
视图:
def editFields(request, shapefile_id):
layer_selected = Shapefile.objects.get(pk=shapefile_id)
attributes_selected= Attribute.objects.filter(shapefile__pk=shapefile_id)
attributesFormset = modelformset_factory(Attribute, form=AttributeForm, extra=1, can_delete=True)
if request.POST:
formset = attributesFormset(request.POST, queryset=attributes_selected)
if formset.is_valid():
instances = formset.save(commit=False)
for instance in instances:
instance.shapefile = layer_selected
try:
instance.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
print non_field_errors
formset = attributesFormset(queryset=attributes_selected)
return render_to_response("basqui/manage_layer_editFields.html", {'shapefile': layer_selected, 'formset':formset}, context_instance=RequestContext(request))
instance.save()
formset = attributesFormset(queryset=attributes_selected)
return render_to_response("basqui/manage_layer_editFields.html", {'shapefile': layer_selected, 'formset':formset}, context_instance=RequestContext(request))
答案 0 :(得分:1)
您的方法的缺点是您已将验证从表单移至视图。
我最近遇到了同样的问题,即验证一个唯一的约束,其中一个字段从模型表单中排除。我的解决方案是覆盖模型表单的clean
方法,并查询数据库以检查唯一的约束。这复制了full_clean
调用的代码,但我喜欢它,因为它是显式的。
我简单地想过覆盖_get_validation_exclusions
,这本来会更干,但我决定不依赖私人api。