2009-04-26 11 views
4

Ich versuche, eine ModelForm und eine inlineformset_factory mit einer Instanz eines Modells aufzufüllen, aber wenn der Benutzer das Formular übergibt, muss ich eine neue Instanz des Modells und seiner zugehörigen untergeordneten Datensätze erstellen.In Django, wie kann ich ein Bearbeitungsformular von einem Modell/Kind vorbelegen, aber die Einreichung als neue Instanz speichern?

Beispielmodell:

class Artist(models.Model): 
    artist = models.CharField(max_length=100) 

class Song(models.Model): 
    artist = models.ForeignKey(Artist) 
    song = models.CharField(max_length=200) 

Ich mag der Benutzer eine Bearbeitungsformular, um zu sehen, basierend auf einer Instanz von Künstlern, zusammen mit einem InlineFormSet für diesen verbundenen Song des Künstlers. Das Formular wird mit den vorhandenen Daten gefüllt und der Benutzer kann den Künstlernamen und die Liednamen ändern. Wenn der Benutzer das Formular jedoch sendet, möchte ich die vorhandenen Datensätze nicht überschreiben. Stattdessen möchte ich eine neue Instanz von Artist erstellen und neue Songs für diesen neuen Künstler hinzufügen.

Ich habe versucht, den Primärschlüssel des Künstlers auf None vor dem Speichern - und das zwingt eine neue Instanz des Künstlers. Ich verliere jedoch die ForeignKey-Beziehung zwischen Künstlern und Songs.

Beispiel Anzeigen:

def edit(request, artist_id=None): 
    if artist_id == None: 
     artistsubmission = Artist() 
    else: 
     artistsubmission = Artist.objects.get(id = artist_id) 
     artistsubmission.pk = None 

    if request.method == 'POST': 
     form = ArtistEditForm(request.POST, instance=artistsubmission) 
     formset = SongFormSet(request.POST, instance=artistsubmission) 

     if form.is_valid() and formset.is_valid(): 
      form.save() 
      formset.save() 
      return HttpResponseRedirect('/success/')  
    else: 
     form = ArtistEditForm(instance=artistsubmission) 
     formset = SongFormSet(instance=artistsubmission) 

    return render_to_response('edit.html', {'form':form, 'formset':formset}) 

Antwort

4

Sie können über die einzelnen Formulare in Ihrem Formularsatz iterieren, ändern, was Sie benötigen und speichern.

+0

Danke - Ich denke, ich könnte das mit einem Modelformset machen, aber nicht mit einem Inlineformset. Es würde erfordern, dass ich Lieder durchliefe, den Anfangswert festlege und dann für jedes Element einen Speichervorgang durchführe. Das fühlt sich an, als würde ich viele Inline-Formset-Funktionen neu erstellen. Wenn ich etwas vermisse, würde ich mich über jeden zusätzlichen Rat freuen. Danke;) –

+0

Ich werde dies als die Antwort markieren und eine andere Frage zu inlineformsets stellen, sobald ich das durcharbeiten kann. Danke noch einmal. –

+0

aber das bedeutet, dass dein Modell für Songs ohne Künstler gültig ist, was ein bisschen komisch ist ... – xster

2

Ich denke, der einfachste Weg, dies zu tun wäre, um Standardwerte zu setzen, indem ein Wörterbuch in als erstes Argument in das Formular übergeben. Sie können alle Felder einer Modellinstanz abrufen nach:

d_initial = Artist.objects.filter(pk=artist_id).values()[0] 

Dies ist das Wörterbuch, das Sie in das Formular übergeben würden.

form = ArtistEditForm(d_initial) 

Wenn Sie etwas aus dem Formular ausgeschlossen haben, möchten Sie es möglicherweise aus dem Wörterbuch entfernen. Gleich für id. Dies sollte jedoch ein Formular erzeugen, das alle Werte der vorhandenen Instanz enthält, aber in einer neuen Instanz gespeichert wird.

+0

Dank - das ist wirklich gut für das Modell funktioniert, aber nicht für die inlineformset_factory. Es scheint, dass inlineformset_factory keine initialen Werte annimmt. –

1

Ich hatte ein ähnliches Problem, und ich löste es wie folgt aus:

def edit(request, artist_id=None): 
    if artist_id == None: 
     artistsubmission = Artist() 
    else: 
     artistsubmission = get_object_or_404(Artist, id = artist_id) 

    if request.method == 'POST': 
     form = ArtistEditForm(request.POST, instance=artistsubmission) 
     formset = SongFormSet(request.POST, instance=artistsubmission) 

     if form.is_valid() and formset.is_valid(): 
      artistsubmission.pk = None 

      artist = form.save(commit=False) 
      artist.id = None 
      artist.save() 

      for f in formset.forms: 
       song = f.save(commit=False) 
       song.artist_id = artist.id 
       song.id = None 
       song.save() 
      return HttpResponseRedirect('/success/') 
    else: 
     form = ArtistEditForm(instance=artistsubmission) 
     formset = SongFormSet(instance=artistsubmission) 
    return render_to_response('edit.html', {'form':form, 'formset':formset})