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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django使用不完整的模型创建一个有效的ModelForm,以在表单验证后手动添加字段相关的知识,希望对你有一定的参考价值。

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

示例代码:

views.朋友

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.朋友

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

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

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

以上是关于Django使用不完整的模型创建一个有效的ModelForm,以在表单验证后手动添加字段的主要内容,如果未能解决你的问题,请参考以下文章

在 django 中为模型创造完整历史的最佳方法是啥?

Django:如何动态创建模型仅用于测试

每次在Django中生成视图时更新模型

基于 JOIN 查询创建 Django 模型

如何在 Django 模型上存储字典?

Django框架(模型层:单表查询)