vistas modal genericas form example create clases based basadas django inline-formset django-class-based-views

modal - vistas basadas en clases django 2



Vistas basadas en clase de django con forma de modelo en lĂ­nea o formset (7)

Acabo de agregar mi propia versión después de verificar algunos de los CBV prefabricados. Específicamente necesitaba control sobre multiple formsets -> one parent en una sola vista, cada uno con funciones de guardado individuales.

Básicamente rellené el enlace de datos FormSet en una función get_named_formsets que es llamada por get_context_data y form_valid .

Allí, compruebo si todos los conjuntos de formularios son válidos, y también busco un método que anule un viejo formset.save() simple por conjunto de formset.save() para el guardado personalizado.

La plantilla procesa formularios a través de

{% with named_formsets.my_specific_formset as formset %} {{ formset }} {{ formset.management_form }} {% endwith %}

Creo que usaré este sistema regularmente.

class MyView(UpdateView): # FormView, CreateView, etc def get_context_data(self, **kwargs): ctx = super(MyView, self).get_context_data(**kwargs) ctx[''named_formsets''] = self.get_named_formsets() return ctx def get_named_formsets(self): return { ''followup'': FollowUpFormSet(self.request.POST or None, prefix=''followup''), ''action'': ActionFormSet(self.request.POST or None, prefix=''action''), } def form_valid(self, form): named_formsets = self.get_named_formsets() if not all((x.is_valid() for x in named_formsets.values())): return self.render_to_response(self.get_context_data(form=form)) self.object = form.save() # for every formset, attempt to find a specific formset save function # otherwise, just save. for name, formset in named_formsets.items(): formset_save_func = getattr(self, ''formset_{0}_valid''.format(name), None) if formset_save_func is not None: formset_save_func(formset) else: formset.save() return http.HttpResponseRedirect('''') def formset_followup_valid(self, formset): """ Hook for custom formset saving.. useful if you have multiple formsets """ followups = formset.save(commit=False) # self.save_formset(formset, contact) for followup in followups: followup.who = self.request.user followup.contact = self.object followup.save()

Tengo los siguientes modelos:

class Bill(models.Model): date = models.DateTimeField(_("Date of bill"),null=True,blank=True) class Item(models.Model): name = models.CharField(_("Name"),max_length=100) price = models.FloatField(_("Price")) quantity = models.IntegerField(_("Quantity")) bill = models.ForeignKey("Bill",verbose_name=_("Bill"), related_name="billitem")

Sé que esto es posible:

from django.forms.models import inlineformset_factory inlineformset_factory(Bill, Item)

y luego procesar esto a través de una vista estándar.

Ahora me preguntaba, si hay una forma de lograr lo mismo (es decir, usar un en línea para agregar / editar elementos que pertenecen a una factura) usando vistas basadas en clases (no para la interfaz de administración).


Deberías probar django-extra-views . Busque CreateWithInlinesView y UpdateWithInlinesView .


El código en la respuesta de Jordan no funcionó para mí. Publiqué mi propia pregunta sobre esto, que creo que ahora he resuelto. El primer argumento para inlineformset_factory debe ser Book, not BookForm.


Hice algunas modificaciones a la solución original para permitir que formset.is_valid () funcione:

if self.request.POST: context[''fs''] = MyInlineFS(self.request.POST, instance=self.object) else: context[''fs''] = MyInlineFS(instance=self.object)


Los puntos clave son:

  1. FormSet generados dentro de forms.py usando inlineformset_factory :

    BookImageFormSet = inlineformset_factory(BookForm, BookImage, extra=2) BookPageFormSet = inlineformset_factory(BookForm, BookPage, extra=5)

  2. devolvió los FormSet s dentro de una clase views.py en views.py :

    def get_context_data(self, **kwargs): context = super(BookCreateView, self).get_context_data(**kwargs) if self.request.POST: context[''bookimage_form''] = BookImageFormSet(self.request.POST) context[''bookpage_form''] = BookPageFormSet(self.request.POST) else: context[''bookimage_form''] = BookImageFormSet() context[''bookpage_form''] = BookPageFormSet() return context

  3. Se utilizó form_valid para guardar el formulario y formset:

    def form_valid(self, form): context = self.get_context_data() bookimage_form = context[''bookimage_formset''] bookpage_form = context[''bookpage_formset''] if bookimage_form.is_valid() and bookpage_form.is_valid(): self.object = form.save() bookimage_form.instance = self.object bookimage_form.save() bookpage_form.instance = self.object bookpage_form.save() return HttpResponseRedirect(''thanks/'') else: return self.render_to_response(self.get_context_data(form=form))


Necesitaba hacer una modificación más a get_context_data() la vista de Jordan y Speq para tener formset.non_form_errors en el contexto de la plantilla.

... if self.request.POST: context[''fs''] = MyInlineFS(self.request.POST, instance=self.object) context[''fs''].full_clean() # <-- new else: context[''fs''] = MyInlineFS(instance=self.object) return context


Redijo el código fuente genérico del 1.3-beta-1:

El código no está listo para la edición de listas o hay algo de magia negra aquí. Pero creo que se puede implementar rápidamente.

Si observa el módulo django.view.generic.edit (que admite edición de objetos detallados) cómo utiliza el módulo django.view.generic.detail.

Creo que se puede implementar un módulo django.view.generic.list_edit usando django.view.generic.list y alguna parte de django.view.generic.edit.