Domanda

Ho i seguenti modelli:

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

So che questo è possibile:

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

e quindi elaborare questo tramite visualizzazione standard.

Ora mi chiedevo, se c'è un modo per ottenere gli stessi (che significa: utilizzando una linea per l'aggiunta / modifica di elementi appartenenti a un disegno di legge) vista utilizzando class basate (non per l'ammi- l'interfaccia).

È stato utile?

Soluzione

Punti chiave è:

  1. FormSets generati all'interno forms.py utilizzando inlineformset_factory:

    BookImageFormSet = inlineformset_factory(BookForm, BookImage, extra=2)
    BookPageFormSet = inlineformset_factory(BookForm, BookPage, extra=5)
    
  2. restituito i FormSets all'interno di una classe CreateView 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. form_valid usato per salvare la forma e 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))
    

Altri suggerimenti

Ho appena aggiunto la mia versione dopo aver controllato alcuni di quei CBVS pre-fatti. In particolare mi serviva il controllo su multiple formsets -> one parent in un'unica vista di ogni individuo con funzioni di risparmio.

In pratica ho farcito i dati formset associazione in una funzione get_named_formsets quale è invocato il get_context_data e form_valid.

Ecco, io controllare se tutte formsets sono validi, e anche cercare un metodo che le sostituzioni una pianura vecchio formset.save() su una base per formset per il risparmio personalizzato.

Il modello rende formsets tramite

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

Credo che sarò con questo sistema regolarmente.

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

Si dovrebbe provare django-extra-vista . Cercare CreateWithInlinesView e UpdateWithInlinesView.

I rosso il codice sorgente generica del 1,3-beta-1:

Il codice non è assolutamente pronto per la modifica List o c'è qualche magia nera qui. Ma penso che possa essere implementata rapidamente.

Se si guarda alla django.view.generic.edit (che il supporto di modifica oggetto dettagliata) modulo come utilizzare il modulo django.view.generic.detail.

Credo che un modulo django.view.generic.list_edit può essere implementato utilizzando django.view.generic.list e una parte da django.view.generic.edit.

Ho fatto qualche modifica alla soluzione originale per far formset.is_valid () al lavoro:

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

Il codice di risposta di Jordan non ha funzionato per me. Ho inviato la mia domanda proprio su questo, che credo ora ho risolto. Il primo argomento di inlineformset_factory deve essere prenotato, non forma di libro.

avevo bisogno di fare un ulteriore modifica al Jordan e get_context_data() di vista di SpeQ in modo da avere formset.non_form_errors esistere nel contesto del modello.

...
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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top