2011-08-25 95 views
1

我已经设置了一个内联使用的MultiValueField。如果我将MultiValueField留为空白,它似乎认为它被填充。结果,我不断收到表单验证错误,因为就形式而言,这些内联不是空的(因此得到验证)。MultiValueField in a optional inline

所以我想我想知道:是否有技巧设置MultiValueField,以便它可以显式空白,以便我可以避免提出验证错误?

这里是有问题的代码:的MutliValueField

class TypedValueField(forms.MultiValueField): 
    def __init__(self, *args, **kwargs): 
     fields = (
        forms.ChoiceField(required=False, choices=[(None, '(type)')] + [(c,c) for c in ['int','float','bool','string']]), 
        forms.CharField(required=False) 
       ) 
     super(TypedValueField, self).__init__(fields, *args, **kwargs) 


    def compress(self, data_list): 
     if data_list: 
      # Raise a validation error if time or date is empty 
      # (possible if SplitDateTimeField has required=False). 
      if data_list[1]=="" or data_list[1]==None: 
       return data_list[1] 
      if data_list[0] == 'bool': 
       try: 
        if data_list[1].lower() == "true": 
         return True 
       except: 
        pass 
       try: 
        if int(data_list[1] == 1): 
         return True 
       except ValueError: 
        raise forms.ValidationError("You must enter True or False") 
       return False 
      if data_list[0] == 'int': 
       try: 
        return int(data_list[1]) 
       except ValueError: 
        raise forms.ValidationError("You must enter a number") 
      if data_list[0] == 'float': 
       try: 
        return float(data_list[1]) 
       except ValueError: 
        raise forms.ValidationError("You must enter a decimal number") 
      if data_list[0] == 'string': 
       return data_list[0] 
      else: 
       raise forms.ValidationError("Invalid data type") 
     return None 


class TypedValueWidget(forms.MultiWidget): 
    def __init__(self, attrs=None): 
     widgets = (
      forms.Select(choices=[(None, '(type)')] + [(c,c) for c in ['int','float','bool','string']]), 
      forms.TextInput() 
     ) 
     super(TypedValueWidget, self).__init__(widgets, attrs) 

    def decompress(self, value): 
     if value: 
      if isinstance(value, bool): 
       return ['bool', value] 
      if isinstance(value, float): 
       return ['float', value] 
      if isinstance(value, int): 
       return ['int', value] 
      if isinstance(value, basestring): 
       return ['string', value] 
      else: 
       raise Exception("Invalid type found: %s" % type(value)) 
     return [None, None] 

class ParamInlineForm(forms.ModelForm): 
    match = TypedValueField(required=False, widget=TypedValueWidget()) 

    class Meta: 
     model = Param 

回答

0

覆盖清洁方法(看看到Django的源)

+0

'SplitDateTimeField'没有'clean'方法,但可以很好地作为可选字段。 –

0

这是我的问题,就在这里:

 fields = (
        forms.ChoiceField(required=False, choices=[(None, '(type)')] + [(c,c) for c in ['int','float','bool','string']]), 
        forms.CharField(required=False) 
       ) 

需要更改为

 fields = (
        forms.ChoiceField(required=False, choices=[("", '(type)')] + [(c,c) for c in ['int','float','bool','string']]), 
        forms.CharField(required=False) 
       ) 

如果使用None的价值在一个选择字段选择,它被呈现为

<option value="None">(type)</option> 

,而不是

<option value="">(type)</option> 

这里是在Django有罪的源代码(在Select部件类别的render_option方法):

 return u'<option value="%s"%s>%s</option>' % (
      escape(option_value), selected_html, 
      conditional_escape(force_unicode(option_label))) 

我想不出任何情况下你会指定None作为一个值,并且想要返回"None"。虽然空值""当然也不同于None