with widgets formularios form fields creating create python django django-forms

python - widgets - formularios django



¿Múltiples modelos en un solo django ModelForm? (5)

¿Es posible tener múltiples modelos incluidos en un único ModelForm en django? Estoy tratando de crear un formulario de edición de perfil. Entonces necesito incluir algunos campos del modelo de Usuario y el modelo de Perfil de Usuario. Actualmente estoy usando 2 formularios como este

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

¿Hay alguna forma de consolidarlos en un solo formulario o simplemente necesito crear un formulario y manejar la carga del db y guardarme a mí mismo?


Probablemente deberías echarle un vistazo a los formularios en línea . Los formularios en línea se usan cuando sus modelos están relacionados por una clave externa.


Puede mostrar ambos formularios en la plantilla dentro de un elemento <form> html. Luego solo procesa los formularios por separado en la vista. Aún podrá usar form.save() y no tendrá que procesar la carga de db y guardarse usted mismo.

En este caso, no debería necesitarlo, pero si va a utilizar formularios con los mismos nombres de campo, busque en el prefix kwarg para los formularios django. (Respondí una pregunta al respecto here ).


Puede verificar mi respuesta aquí para un problema similar.

Habla sobre cómo combinar el registro y el perfil de usuario en un solo formulario, pero se puede generalizar a cualquier combinación de ModelForm.


Puedes intentar usar estos pedazos de código:

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

Ejemplo de uso:

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


erikbwork y yo teníamos el problema de que uno solo puede incluir un modelo en una vista genérica basada en la clase. Encontré una forma similar de abordarlo como Miao, pero más modular.

Escribí un Mixin para que pueda usar todas las vistas basadas en clases genéricas. Defina el modelo, los campos y ahora también child_model y child_field, y luego puede ajustar los campos de ambos modelos en una etiqueta como describe 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())

Ejemplo de uso:

class ConsumerRegistrationUpdateView(UpdateView): model = Registration fields = (''firstname'', ''lastname'',) child_model = ConsumerProfile child_fields = (''payment_token'', ''cart'',)

O con ModelFormClass:

class ConsumerRegistrationUpdateView(UpdateView): model = Registration fields = (''firstname'', ''lastname'',) child_model = ConsumerProfile child_form_class = ConsumerProfileForm

Hecho. Espero que ayude a alguien.