Django-验证modelform_工厂中禁用的字段

Django-验证modelform_工厂中禁用的字段,django,django-forms,Django,Django Forms,我使用modelform_factory生成带有额外表单的modelforms。对于具有实例的表单,类型字段处于禁用状态,对于额外表单,该字段处于启用状态 在save()上,表单不会进行验证,因为POST中没有针对禁用字段的数据。即使是自定义的clean方法也不起作用()。我想跳过对禁用字段的验证,或者有办法保留此字段的实例数据。 models.py class Attribute(models.Model): shapefile = models.ForeignKey(Shapefil

我使用modelform_factory生成带有额外表单的modelforms。对于具有实例的表单,类型字段处于禁用状态,对于额外表单,该字段处于启用状态

在save()上,表单不会进行验证,因为POST中没有针对禁用字段的数据。即使是自定义的clean方法也不起作用()。我想跳过对禁用字段的验证,或者有办法保留此字段的实例数据。

models.py

class Attribute(models.Model):
    shapefile = models.ForeignKey(Shapefile)
    name = models.CharField(max_length=255)
    type = models.IntegerField()
    width = models.IntegerField()
    precision = models.IntegerField()

    def __unicode__(self):
        return self.name
forms.py

FIELD_TYPE = [('', '--Choose a type--'),
                    (0, 'Integer'),
                    (1, 'Integer list'),
                    (2, 'Double Precision Float'),
                    (3, 'List of doubles'),
                    (4, 'String of ASCII chars'),
                    (5, 'Array of strings'),
                    (8, 'Raw Binary data'),
                    (9, 'Date'),
                    (10, 'Time'),
                    (11, 'Date and Time')]

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['width'].widget.attrs['readonly'] = True
            self.fields['precision'].widget.attrs['readonly'] = True

    type = forms.ChoiceField(choices=FIELD_TYPE)

    class Meta:
        model = Attribute
        exclude = ['shapefile']
views.py

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)
        formset.save()
    else:
        formset = attributesFormset(queryset=attributes_selected)

    return render_to_response("ezmapping/editFields.html", {'shapefile': layer_selected, 'formset':formset}, context_instance=RequestContext(request))

有很多方法,但我认为这一种相当优雅(假设它确实有效;第一次检查时看起来不错,但我还没有测试)

在窗体上,有条件地将该字段设置为非必需,然后声明一个自定义清理方法:

def __init__(self):
    # as above, until here
        self.fields['type'].widget.attrs['disabled'] = True
        self.fields['type'].required = False
    # then continue as above

def clean_type(self):
    if self.instance and self.instance.pk:
        return self.instance.type
    else:
        return self.cleaned_data['type']

将其设置为not required意味着在验证该字段的过程中,该字段不会立即短路,并且该字段的自定义清除方法返回实例的未修改值,以便在从表单构造修改的实例时,不会使用
None
覆盖该实例。对于给定空值或根本没有值的必填字段,不调用自定义清理方法。

有许多方法,但我认为这一种方法相当优雅(假设它确实有效;第一次检查时它看起来不错,但我还没有测试它)

在窗体上,有条件地将该字段设置为非必需,然后声明一个自定义清理方法:

def __init__(self):
    # as above, until here
        self.fields['type'].widget.attrs['disabled'] = True
        self.fields['type'].required = False
    # then continue as above

def clean_type(self):
    if self.instance and self.instance.pk:
        return self.instance.type
    else:
        return self.cleaned_data['type']

将其设置为not required意味着在验证该字段的过程中,该字段不会立即短路,并且该字段的自定义清除方法返回实例的未修改值,以便在从表单构造修改的实例时,不会使用
None
覆盖该实例。对于给定空值或根本没有值的必填字段,不调用自定义清理方法。

它不起作用。由于该字段被禁用,它似乎没有调用clean方法。。。如果该字段是只读的,而不是disabled@Burton449-在设置小部件的禁用属性的同时,还可以尝试在
\uuuu init\uuuu
中设置
self.fields['type'].required=False
。实际上,即使没有自定义的
clean_type
,这也足够了。自定义的
clean_type
应该解决这个问题,如果
required=False
,即使帖子中没有提供空值,也会返回一个非空值。是的,这是有效的,也许你应该完成完整的答案。它不起作用。由于该字段被禁用,它似乎没有调用clean方法。。。如果该字段是只读的,而不是disabled@Burton449-在设置小部件的禁用属性的同时,还可以尝试在
\uuuu init\uuuu
中设置
self.fields['type'].required=False
。实际上,即使没有自定义的
clean_type
,这也足够了。自定义的
clean_type
应该解决这个问题,如果
required=False
,即使帖子中没有提供空值,也会返回一个非空值。是的,这很有效,也许你应该完成完整的答案。