widgets update formularios form fields example avanzados python django design django-forms

python - update - modelform django



Django: mĂșltiples modelos en una plantilla usando formularios (7)

Estoy construyendo una aplicación de seguimiento de tickets de soporte y tengo algunos modelos que me gustaría crear desde una página. Los boletos pertenecen a un cliente a través de una clave externa. Las notas también pertenecen a Tickets a través de ForeignKey. Me gustaría tener la opción de seleccionar un cliente (es decir, un proyecto completo) o crear un nuevo cliente, luego crear un ticket y finalmente crear una nota asignada al nuevo ticket.

Como soy bastante nuevo en Django, tiendo a trabajar iterativamente, probando nuevas funciones cada vez. He jugado con ModelForms pero quiero ocultar algunos de los campos y realizar una validación compleja. Parece que el nivel de control que estoy buscando requiere formularios o hacer todo a mano, completo con una página de plantilla tediosa y codificada a mano, que estoy tratando de evitar.

¿Hay alguna característica preciosa que me falta? ¿Alguien tiene una buena referencia o ejemplo para usar formsets? Pasé todo un fin de semana en los documentos de API para ellos y todavía no tengo ni idea. ¿Es un problema de diseño si rompo y código de la mano todo?


"Quiero ocultar algunos de los campos y hacer una validación compleja".

Comienzo con la interfaz de administración incorporada.

  1. Construya ModelForm para mostrar los campos deseados.

  2. Extienda el formulario con las reglas de validación dentro del formulario. Por lo general, este es un método clean .

    Asegúrese de que esta parte funcione razonablemente bien.

Una vez hecho esto, puede alejarse de la interfaz de administración incorporada.

Entonces puede jugar con múltiples formularios parcialmente relacionados en una sola página web. Este es un montón de material de plantilla para presentar todos los formularios en una sola página.

Luego debe escribir la función de vista para leer y validar los diversos elementos de forma y hacer los diversos objetos save ().

"¿Es un problema de diseño si rompo y código de la mano todo?" No, es mucho tiempo para no obtener muchos beneficios.


Actualmente tengo una solución alternativa funcional (pasa las pruebas de mi unidad). Es una buena solución para mi opinión cuando solo quiere agregar un número limitado de campos de otros modelos.

Me estoy perdiendo de algo ?

class UserProfileForm(ModelForm): def __init__(self, instance=None, *args, **kwargs): # Add these fields from the user object _fields = (''first_name'', ''last_name'', ''email'',) # Retrieve initial (current) data from the user object _initial = model_to_dict(instance.user, _fields) if instance is not None else {} # Pass the initial data to the base super(UserProfileForm, self).__init__(initial=_initial, instance=instance, *args, **kwargs) # Retrieve the fields from the user model and update the fields with it self.fields.update(fields_for_model(User, _fields)) class Meta: model = UserProfile exclude = (''user'',) def save(self, *args, **kwargs): u = self.instance.user u.first_name = self.cleaned_data[''first_name''] u.last_name = self.cleaned_data[''last_name''] u.email = self.cleaned_data[''email''] u.save() profile = super(UserProfileForm, self).save(*args,**kwargs) return profile



El MultiModelForm de django-betterforms es un contenedor conveniente para hacer lo que se describe en la respuesta de Gnudiff . Envuelve regularmente ModelForm s en una sola clase que es transparente (al menos para uso básico) utilizada como una sola forma. Copié un ejemplo de sus documentos a continuación.

# forms.py from django import forms from django.contrib.auth import get_user_model from betterforms.multiform import MultiModelForm from .models import UserProfile User = get_user_model() class UserEditForm(forms.ModelForm): class Meta: fields = (''email'',) class UserProfileForm(forms.ModelForm): class Meta: fields = (''favorite_color'',) class UserEditMultiForm(MultiModelForm): form_classes = { ''user'': UserEditForm, ''profile'': UserProfileForm, } # views.py from django.views.generic import UpdateView from django.core.urlresolvers import reverse_lazy from django.shortcuts import redirect from django.contrib.auth import get_user_model from .forms import UserEditMultiForm User = get_user_model() class UserSignupView(UpdateView): model = User form_class = UserEditMultiForm success_url = reverse_lazy(''home'') def get_form_kwargs(self): kwargs = super(UserSignupView, self).get_form_kwargs() kwargs.update(instance={ ''user'': self.object, ''profile'': self.object.profile, }) return kwargs


Esto realmente no es demasiado difícil de implementar con ModelForms . Entonces digamos que tiene los formularios A, B y C. Imprime cada uno de los formularios y la página y ahora necesita manejar el POST.

if request.POST(): a_valid = formA.is_valid() b_valid = formB.is_valid() c_valid = formC.is_valid() # we do this since ''and'' short circuits and we want to check to whole page for form errors if a_valid and b_valid and c_valid: a = formA.save() b = formB.save(commit=False) c = formC.save(commit=False) b.foreignkeytoA = a b.save() c.foreignkeytoB = b c.save()

Here están los documentos para la validación personalizada.


Estuve en la misma situación hace un día, y aquí están mis 2 centavos:

1) Encontré sin duda la demostración más breve y concisa de la entrada de modelos múltiples en una sola forma aquí: http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/ .

En pocas palabras: haga un formulario para cada modelo, envíe los dos a la plantilla en un solo <form> , use el prefix keyarg y tenga la validación del identificador de vista. Si hay dependencia, solo asegúrese de guardar el modelo "principal" antes de dependiente, y use la identificación del padre para la clave externa antes de guardar el modelo "hijo". El enlace tiene la demo.

2) Tal vez los conjuntos de formularios pueden ser golpeados para hacer esto, pero en lo que yo profundicé, los conjuntos de formularios son principalmente para ingresar múltiplos del mismo modelo, que pueden estar opcionalmente vinculados a otro modelo / modelos mediante claves externas. Sin embargo, parece que no hay una opción predeterminada para ingresar más de los datos de un modelo y no es para lo que se define el formset.


Recientemente tuve un problema y simplemente descubrí cómo hacer esto. Suponiendo que tiene tres clases, Primaria, B, C y esa B, C tiene una clave externa a primaria

class PrimaryForm(ModelForm): class Meta: model = Primary class BForm(ModelForm): class Meta: model = B exclude = (''primary'',) class CForm(ModelForm): class Meta: model = C exclude = (''primary'',) def generateView(request): if request.method == ''POST'': # If the form has been submitted... primary_form = PrimaryForm(request.POST, prefix = "primary") b_form = BForm(request.POST, prefix = "b") c_form = CForm(request.POST, prefix = "c") if primary_form.is_valid() and b_form.is_valid() and c_form.is_valid(): # All validation rules pass print "all validation passed" primary = primary_form.save() b_form.cleaned_data["primary"] = primary b = b_form.save() c_form.cleaned_data["primary"] = primary c = c_form.save() return HttpResponseRedirect("/viewer/%s/" % (primary.name)) else: print "failed" else: primary_form = PrimaryForm(prefix = "primary") b_form = BForm(prefix = "b") c_form = Form(prefix = "c") return render_to_response(''multi_model.html'', { ''primary_form'': primary_form, ''b_form'': b_form, ''c_form'': c_form, })

Este método debería permitirle hacer la validación que requiera, así como generar los tres objetos en la misma página. También he usado javascript y campos ocultos para permitir la generación de múltiples objetos B, C en la misma página.