2009-04-26 2 views
4

Я пытаюсь предварительно заполнить ModelForm и inlineformset_factory экземпляром модели, НО, когда пользователь отправляет форму, мне нужно создать новый экземпляр модели и связанные дочерние записи.В Django, как я могу предварительно заполнить форму редактирования из модели/дочернего элемента, но сохранить представление как новый экземпляр?

Пример Модель:

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

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

Я хочу, чтобы пользователь, чтобы увидеть форму редактирования на основе экземпляра художника, наряду с InlineFormSet для связанных песни, которые Художника. Форма будет предварительно заполнена существующими данными, и пользователь может изменить имя исполнителя и имена песен. Однако, когда пользователь отправляет форму, я не хочу перезаписывать существующие записи. Вместо этого я хочу создать новый экземпляр Artist и добавить новые песни для этого нового исполнителя.

Я попытался настроить первичный ключ исполнителя на None перед сохранением - и это заставляет новый экземпляр Artist. Тем не менее, я теряю отношения ForeignKey между Художниками и Песнями.

Пример Вид:

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

ответ

4

Вы можете перебирать отдельные формы в своем наборе форм, изменять то, что вам нужно, и сохранять.

if form.is_valid() and formset.is_valid(): 
    artist = form.save() 
    for f in formset.forms: 
     song = f.save(commit=False) 
     song.artist = artist.id 
     song.save() 
+0

Спасибо - я думаю, что смогу сделать эту работу с modelformset, но не встроенным форматом. Это потребует, чтобы я прокрутил песни, установил начальное значение, а затем выполнил сохранение для каждого элемента. Это похоже на то, что я буду воссоздать многие возможности inlineformset. Если мне что-то не хватает, я буду благодарен за любые дополнительные советы. Спасибо;) – 2009-04-26 22:39:17

+0

Я буду отмечать это как ответ и задавать другой вопрос о встроенных формах, как только я это проработаю. Еще раз спасибо. – 2009-04-26 22:44:41

+0

, но это означает, что ваша модель для песни действительна без художника, который немного странный ... – xster

2

Я думаю, что самый простой способ сделать это было бы, чтобы установить значения по умолчанию, передавая словарь в качестве первого аргумента в форму. Вы можете получить все ПОЛЕЙ экземпляр модели пути:

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

Это словарь, который вы хотите передать в форму.

form = ArtistEditForm(d_initial) 

Если вы исключили что-либо из формы, вы можете удалить ее из словаря. То же самое для id. Но это должно создать форму, которая имеет все значения из существующего экземпляра, но сохранит ее в новом экземпляре.

+0

Спасибо - это работает очень хорошо для модели, но не для inlineformset_factory. Кажется, что inlineformset_factory не принимает начальные значения. – 2009-04-26 18:07:56

1

У меня была аналогичная проблема, и я решил ее так:

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