Django使用无效的模型创建有效的ModelForm,以在表单验证后手动添加字段

时间:2018-08-19 20:03:59

标签: django django-forms django-validation

如何创建一个发布请求以使ModelForm有效(为您提供用户需要填写的所有内容),然后更改模型(为用户提供不必提供的所有内容,例如用户名/个人资料,日期时间,其他可计算变量等...]),然后在视图中验证表单/表单集?

示例代码:

views.py

def view(request):
    # Create the formset, specifying the form and formset we want to use.
    LowerFormSet = formset_factory(LowerForm, formset=BaseLowerFormSet, extra=0)

    # If they are posting data
    if request.method == 'POST':
        # Grab the data they submitted
        formData = request.POST
        # highestForm = MealForm(formData, meal=meal, prefix='recipe')

        lower_formset = LowerFormSet(formData, prefix='lower_formset')

        lower_form in lower_formset:
            lower_form.instance.a = A.objects.create(…)

            # HERE
            # Each form isn't valid, because it is missing its associated higher object, despite not including the field in the ModelForm
            lower_form.save()
            # But if we create a foreign key/higher object and add it here, we are circumventing the  validation step, and creating objects when the validation might not be True
            lower_form.instance.higher = Higher.objects.create(…)
            lower_form.save()
            # How do you separate these concerns, so you can create a valid Model Form, then add the necessary parts after the validation?

        # Check for valid data
        if all([otherForm.is_valid(),
                lower_formset.is_valid(),
                other_formset.is_valid(),
                ]):
            # make the Higher here, and add it to each form
            for form in lower_formset:
                form.higher = higher
                form.save()

            return HttpResponseRedirect(reverse('recipe:success'))
        else:
            return response = render(request, 'template', {…})
    else:
        # …

models.py

class Lower(models.Model):
    higher = models.ForeignKey(Higher, related_name="higher")
    # Etiher A or B is required, depending on information from the foreign key of the Higher
    a = models.ForeignKey(A, blank=True, null=True, related_name="switch_case")
    b = models.ForeignKey(B, blank=True, null=True, related_name="switch_case")
    createdAt = models.DateTimeField(auto_now_add=True)

    def clean(self):
        if self.higher.a:
            if not self.a:
                raise AssertionError("The higher wants a, but you did not provide a")
            if self.b:
                raise AssertionError("The higher wants a, but you provided b")
        else:
            if not self.a:
                raise AssertionError("The higher wants b, but you provided a")
            if self.b:
                raise AssertionError("The higher wants b, but you did not provide b")

    def save(self, *args, **kwargs):
        self.clean()
        super(Lower, self).save(*args, **kwargs)

1 个答案:

答案 0 :(得分:2)

您会因考虑无效表格而感到困惑。在对表单进行任何操作之前,表单必须始终有效,但这并不意味着它必须表示模型的有效实例。您需要做的是排除您不想显示给用户的字段,然后在实例上设置这些字段。

class LowerForm(forms.ModelForm):
    class Meta:
        model = Lower
        exclude = ['higher']

和视图:

lower_formset = LowerFormSet(formData, prefix='lower_formset')

if lower_formset.is_valid():   # perform validation
    for lower_form in lower_formset:
        lower = lower_form.save(commit=False)  # create a Lower instance but don't save to db yet
        lower.higher = Higher.objects.create(…)
        lower.save()