来自不同模型的Django多格式验证

时间:2019-07-10 21:01:31

标签: django django-models django-forms

我一直在努力规范化我在Django中拥有的一些表/模型,这些表/模型将以一种较大的形式使用。

假设我有2种基于2种模型的表格,其中1种依赖于其他模型。当在其他模型中进行特定选择时,是否可以在一种模型中添加表单验证?

1个表单中的cleaned_data在其他表单中不可用,是主要问题。我已经在同一个视图中实例化了这两种形式。

所以基本上,我需要以一种形式引用不同模型中的字段(在同一页面上实例化的不同modelForm)

基于表格/模型2的Form2:

def clean(self):
    cleaned_data = super().clean()
    if 'model1_field' in cleaned_data and not cleaned_data['model2_field']:
      self.add_error('model2_field', forms.ValidationError('This field is required.'))
    else:
       print('No validations are needed')

有关依赖性的更多详细信息(尝试遵循db规范化的概念),并且只有在选择了model1中的“ selection2”或“ is_option1”时,model2中才需要一堆字段。

--- Models------
MULTI_OPTIONS = (
    ('selection1', 'selection1'), 
    ('selection2', 'selection2') # Display and make model2 required
)

class Model1(models.Model):
    primary_key = models.CharField(db_column='primary_table1_key', max_length=10) # Maps tocommon key for all related tables

    is_selected = models.BooleanField(db_column='IsSelected', blank=True, default=None)

    multi_select_options = MultiSelectField(db_column='SelectedOptions', max_length=150, choices = MULTI_OPTIONS, blank=True, null=True)  
    is_option1 = models.BooleanField(db_column='IsOption1', blank=True, null=True, default=None) # No validations needed for Model1SubOptions
    is_option2  = models.BooleanField(db_column='IsOption2', blank=True, null=True, default=None)# If option2 or 'selection2' is made in Model1, then make required sub_selections and all other fields in Model1SubOptions

    class Meta:
        managed = True


# This should become required if Model1 specific option (from a multiselect (Or) a specific boolean field is set to true)
class Model2(models.Model):
    primary_key = models.CharField(db_column='primary_table1_key', max_length=10) # Maps tocommon key for all related tables
    sub_selections = MultiSelectField(db_column='SubOptions', max_length=150, choices = (('Some', 'Some'), ('Other','Other')), blank=True, null=True)
   other_field2 = models.PositiveIntegerField(db_column='OtherField2', blank=True, null=True)

---------- Forms ---------
class Model1Form(forms.ModelForm):
    class Meta:
        model = models.Model1
        fields = (  'is_selected', 'multi_select_options', 'is_option1', 'is_option2')

        def clean(self):
            cleaned_data = super().clean()
             if('multi_select_options' in cleaned_data):
                multi_select_options = cleaned_data['multi_select_options']
                if(not multi_select_options): 
                     self.add_error('multi_select_options', forms.ValidationError('This field is required')) 
            #  if(('selection1' in multi_select_options) and check_data_does_not_exist(cleaned_data, 'model2')):
                # Validate model2


class Model2Form(forms.ModelForm):
    class Meta:
        model = models.Model2
        fields = (  'sub_selections', 'other_field2')

        def clean(self):
            cleaned_data = super().clean()
            #  if(('selection1' in multi_select_options) and check_data_does_not_exist(cleaned_data, 'multi_select_options')):
                # Validate model2

1 个答案:

答案 0 :(得分:0)

您可以创建一个包含两个模型中所有字段的表单,然后可以使用一种干净的方法进行所有验证,然后您的视图可以处理保存单个模型的情况

class CombinedForm(forms.Form):

    # All fields from Model1
    # All fields from Model2

    def clean(self):
        # Do all validation for fields that are dependent on each other


class CombinedView(FormView):

    form_class = CombinedForm

    def form_valid(self, form):
        Model1.objects.create(
            param1=form.cleaned_data['param1'],
            param2=form.cleaned_data['param2'],
        )
        Model2.objects.create(
            param3=form.cleaned_data['param3'],
            param4=form.cleaned_data['param4'],
        )