单个Django ModelForm中的多个模型?

是否有可能在django中的单个ModelForm中包含多个模型? 我正在尝试创build一个configuration文件编辑窗体。 所以我需要包含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") 

有没有办法将这些合并成一个forms,或者我只需要创build一个窗体,并处理数据库加载和保存自己?

您可以在一个<form> html元素的模板中显示这两个表单。 然后在视图中分别处理表单。 你仍然可以使用form.save() ,而不必处理数据库加载和保存自己。

在这种情况下,你不需要它,但是如果你要使用具有相同字段名称的表单,请查看django表单的prefix kwarg。 (我在这里回答了一个问题)。

你可以尝试使用这段代码:

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

你可能应该看看内联formset 。 当您的模型与外键关联时,将使用内联表单。

你可以在这里查看我的答案是否有类似的问题。

它讨论了如何将注册和用户configuration文件组合到一个表单中,但是它可以推广到任何ModelForm组合。

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 

完成。 希望能帮助别人。