Frage

Ich habe die folgenden Modelle:

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

Ich weiß, dass dies möglich ist:

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

und diese dann über Standardansicht bearbeiten.

Nun ich habe mich gefragt, ob es eine Möglichkeit ist, die gleichen (was bedeutet: mit einem Inline zum Hinzufügen / Bearbeiten von Elementen, die zu einer Rechnung) zu erreichen, mit Klasse basierten Ansichten (nicht für den Admin- Schnittstelle).

War es hilfreich?

Lösung

Das Wichtigste ist:

  1. erzeugt FormSets innerhalb forms.py mit inlineformset_factory:

    BookImageFormSet = inlineformset_factory(BookForm, BookImage, extra=2)
    BookPageFormSet = inlineformset_factory(BookForm, BookPage, extra=5)
    
  2. ergab FormSets innerhalb einer CreateView Klasse in 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. Gebrauchte form_valid die Form und formset zu speichern:

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

Andere Tipps

ich meine eigene Version nur hinzugefügt, nachdem einige dieser vorgefertigten CBVS Check-out. Ich speziell die Kontrolle über multiple formsets -> one parent in einer einzigen Ansicht mit jeweils individuellen benötigten Funktionen speichern.

Ich stopfte im Grunde die FormSet Daten in eine get_named_formsets Funktion Bindung, die durch get_context_data und form_valid genannt wird.

Es, überprüfe ich, ob alle Formularsätze gültig sind, und suche auch nach einem Verfahren, das hebt eine einfache alte formset.save() auf einem pro formset Basis für individuelle Einsparung.

Die Vorlage macht Formularsätze über

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

Ich denke, ich werde dieses System regelmäßig werden.

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

Sie sollten versuchen, django-extra-Ansichten . Suchen Sie nach CreateWithInlinesView und UpdateWithInlinesView.

I rot die generische Quellcode des 1,3-beta-1:

Der Code ist absolut nicht bereit für Listenbearbeitung oder gibt es einige schwarze Magie hier. Aber ich glaube, dass sie schnell umgesetzt werden kann.

Wenn Sie an der django.view.generic.edit aussehen (diese Unterstützung detaillierte Objektbearbeitung) Modul, wie es das django.view.generic.detail Modul verwenden.

ich denke, dass ein django.view.generic.list_edit Modul django.view.generic.list und einen Teil von django.view.generic.edit umgesetzt werden kann.

Ich habe einige Änderungen zur ursprünglichen Lösung zu lassen formset.is_valid () zu arbeiten:

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

Ich brauchte eine weitere Modifikation Jordaniens und speq Ansicht der get_context_data() zu haben, um formset.non_form_errors exist in der Vorlage Kontext zu machen.

...
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
scroll top