2013-09-25 74 views
0

我使用modelform_factory生成具有額外表單的模型。對於具有實例的表單,類型字段被禁用,對於額外的表單,該字段已啓用。Django - 驗證modelform_factory中的禁用字段

在保存()表單不驗證,因爲沒有數據在禁用字段的POST中。即使是自定義的清潔方法也不起作用(see this answer)。我想跳過對禁用字段的驗證,或者有辦法保留此字段的實例數據。

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)) 

回答

2

有許多方法在那裏,但我覺得這是一個相當優雅(假設它確實有效;它在第一次檢查時看起來正確,但我沒有測試過它)。

https://stackoverflow.com/a/5994681/2337736

在您的形式,有條件地設置字段不需要再申報一個自定義的清潔方法:

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'] 

將其設置爲不要求意味着該場立即不短路在該字段的驗證過程中,該字段的自定義清理方法將返回該實例的未修改值,以便在從窗體構造修改的實例時不會覆蓋None。自定義清理方法不會爲必填字段提供空值或根本沒有值。

+0

它不起作用。因爲該字段被禁用,所以它似乎不會調用乾淨的方法......如果該字段是隻讀的,但禁用時則不會工作 –

+0

@ Burton449 - 嘗試設置'self.fields ['type']。required = False'在'__init__'中同時爲widget設置了disabled屬性。實際上,即使沒有自定義的「clean_type」,這可能就足夠了。 –

+0

即使在POST中沒有提供非空值,自定義'clean_type'應該照顧到'required = False'。 –