问题:单个Django ModelForm中有多个模型?
ModelFormDjango 是否可以在一个模型中包含多个模型?我正在尝试创建个人资料编辑表单。因此,我需要包括User模型和 UserProfile模型中的某些字段。目前我正在使用2种形式
class UserEditForm(ModelForm):
    class Meta:
        model = User
        fields = ("first_name", "last_name")
class UserProfileForm(ModelForm):
    class Meta:
        model = UserProfile
        fields = ("middle_name", "home_phone", "work_phone", "cell_phone")
有没有一种方法可以将这些合并为一个表单,或者我是否只需要创建一个表单并处理数据库加载并保存自己?
回答 0
您可以只在一个<form>html元素内的模板中显示两种形式。然后,只需在视图中分别处理表单即可。您仍然可以使用数据库,form.save()而不必自己进行数据库加载和保存。
在这种情况下,您不需要它,但是如果您要使用具有相同字段名的表单,请查看prefixdjango表单的kwarg。(我在这里回答了一个问题)。
回答 1
您可以尝试使用以下代码:
class CombinedFormBase(forms.Form):
    form_classes = []
    def __init__(self, *args, **kwargs):
        super(CombinedFormBase, self).__init__(*args, **kwargs)
        for f in self.form_classes:
            name = f.__name__.lower()
            setattr(self, name, f(*args, **kwargs))
            form = getattr(self, name)
            self.fields.update(form.fields)
            self.initial.update(form.initial)
    def is_valid(self):
        isValid = True
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            if not form.is_valid():
                isValid = False
        # is_valid will trigger clean method
        # so it should be called after all other forms is_valid are called
        # otherwise clean_data will be empty
        if not super(CombinedFormBase, self).is_valid() :
            isValid = False
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            self.errors.update(form.errors)
        return isValid
    def clean(self):
        cleaned_data = super(CombinedFormBase, self).clean()
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            cleaned_data.update(form.cleaned_data)
        return cleaned_data
用法示例:
class ConsumerRegistrationForm(CombinedFormBase):
    form_classes = [RegistrationForm, ConsumerProfileForm]
class RegisterView(FormView):
    template_name = "register.html"
    form_class = ConsumerRegistrationForm
    def form_valid(self, form):
        # some actions...
        return redirect(self.get_success_url())
回答 2
我和erikbwork都有一个问题,即一个模型只能包含在一个通用的基于类的视图中。我找到了类似苗的类似方法,但是更加模块化。
我写了一个Mixin,因此您可以使用所有通用的基于类的视图。定义模型,字段,现在还定义child_model和child_field-然后可以将两个模型的字段包装在标签中,如Zach描述。
class ChildModelFormMixin: 
    ''' extends ModelFormMixin with the ability to include ChildModelForm '''
    child_model = ""
    child_fields = ()
    child_form_class = None
    def get_child_model(self):
        return self.child_model
    def get_child_fields(self):
        return self.child_fields
    def get_child_form(self):
        if not self.child_form_class:
            self.child_form_class = model_forms.modelform_factory(self.get_child_model(), fields=self.get_child_fields())
        return self.child_form_class(**self.get_form_kwargs())
    def get_context_data(self, **kwargs):
        if 'child_form' not in kwargs:
            kwargs['child_form'] = self.get_child_form()
        return super().get_context_data(**kwargs)
    def post(self, request, *args, **kwargs):
        form = self.get_form()
        child_form = self.get_child_form()
        # check if both forms are valid
        form_valid = form.is_valid()
        child_form_valid = child_form.is_valid()
        if form_valid and child_form_valid:
            return self.form_valid(form, child_form)
        else:
            return self.form_invalid(form)
    def form_valid(self, form, child_form):
        self.object = form.save()
        save_child_form = child_form.save(commit=False)
        save_child_form.course_key = self.object
        save_child_form.save()
        return HttpResponseRedirect(self.get_success_url())
用法示例:
class ConsumerRegistrationUpdateView(UpdateView):
    model = Registration
    fields = ('firstname', 'lastname',)
    child_model = ConsumerProfile
    child_fields = ('payment_token', 'cart',)
或使用ModelFormClass:
class ConsumerRegistrationUpdateView(UpdateView):
    model = Registration
    fields = ('firstname', 'lastname',)
    child_model = ConsumerProfile
    child_form_class = ConsumerProfileForm
做完了 希望能对某人有所帮助。
回答 3
您可能应该看一下Inline表单集。当模型通过外键关联时,将使用内联表单集。
回答 4
回答 5
我在项目中使用了django Betterforms的MultiForm和MultiModelForm。但是,可以改进代码。例如,它依赖于django.six,而3. +不支持,但所有这些都可以轻松修复。
	声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

