BoJack Horseman
BoJack Horseman

Reputation: 4460

Use two forms at the same time

I want to submit two forms in my template. The reason for that is, that I have two separate models, each with a model form, which I have to submit at the same time to create the desired result:

I have these two forms:

class BootstrapModelForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(BootstrapModelForm, self).__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })

class DeckForm(ModelForm):
    class Meta:
        model = Deck
        exclude = ('dust',)

class GuideForm(BootstrapModelForm):
    class Meta:
        model = Guide
        exclude = ('author', 'upvotes', 'downvotes', 'release_date', 'modified', 'deck')

    def __init__(self, *args, **kwargs):
        super(GuideForm, self).__init__(*args, **kwargs)
        self.fields['title'].label = 'Title of your AWESOME Guide!'
        self.fields['public'].label = 'Check, when you want to make your guide public'
        self.fields['public'].widget.attrs.update({
            'class': 'checkbox'
        })
        self.fields['introduction'].label = 'Introduction (not required, but recommended)'

A deck is a part of the Guide that gets created. Since the user should be able to create his own deck while writing his guide, I need two forms.

In my views I handled it like this:

def guide_create(request):
    if request.method == "POST":
        deck_form  =  DeckForm(request.POST)
        guide_form = GuideForm(request.POST)
        if guide_form.is_valid() and deck_form.is_valid():
            new_deck  = deck_form.save(commit=False)
            new_deck.dust = 0
            new_deck.save()

            new_guide = deck_form.save(commit=False)
            new_guide.author = Account.objects.get(id=request.user.id)
            new_guide.deck = Deck.objects.get(id=new_deck.id)
            new_guide.save()
        else:
            print(guide_form.errors)
            print(deck_form.errors)
    else:
        deck_form = DeckForm(prefix = 'DeckForm')
        guide_form = GuideForm(prefix = 'GuideForm')

    return render(request, 'hsguides/guide_create.html', {
        'DeckForm': DeckForm,
        'GuideForm': GuideForm,
    })

I use commit=False so I still can insert the deck in my guide. Now my problem comes with creating the template. When I submit the forms with my current set up, I receive no errors any more but the guide and the deck aren't saved either!

<div style="width: 60%; margin: 0 auto;">

  <form class="form-horizontal" method="POST" action="{% url 'GuideCreate' %}"> {% csrf_token %}
    <fieldset>
      {% for field in DeckForm %}
        {% if field.errors %}
          <div class="class-group error">
            <label class="control-lable">{{ field.label }}</label>
            <div class="controls">{{ field }}
              <span class="help-inline">
                {% for error in  field.errors %}{{ error }}{% endfor %}
              </span>
            </div>
          </div>
        {% else %}
          <div class="control-group">
            <label class="control-label">{{ field.label }}</label>
            <div class="controls">{{ field }}</div>
          </div>
        {% endif %}
      {% endfor %}
    </fieldset>


    <fieldset>
      {% for field in GuideForm %}
        {% if field.errors %}
          <div class="class-group error">
            <label class="control-lable">{{ field.label }}</label>
            <div class="controls">{{ field }}
              <span class="help-inline">
                {% for error in  field.errors %}{{ error }}{% endfor %}
              </span>
            </div>
          </div>
        {% else %}
          <div class="control-group">
            <label class="control-label">{{ field.label }}</label>
            <div class="controls">{{ field }}</div>
          </div>
        {% endif %}
      {% endfor %}
    </fieldset>

    <div class="form-actions" style="margin-top: 4px;">
      <button type="submit" class="btn btn-default">Submit</button>
    </div>

  </form>
</div>

Edit I don't receive an error message any more, the deck gets created as well but the guide that belongs to it not.

Upvotes: 1

Views: 388

Answers (4)

vlad-ardelean
vlad-ardelean

Reputation: 7622

You're saying the guide doesn't get created. I see this line new_guide = deck_form.save(commit=False)..... shouldn't it be new_guide = guide_form.save(commit=False) ? Not 100% but this might be a mistake. Hopefully, it's not just because you refactored the code for putting it here.

Upvotes: 1

Jesus Gomez
Jesus Gomez

Reputation: 1520

Just Change

return render_to_response('hsguides/guide_create.html', {
    'DeckForm': DeckForm,
    'GuideForm': GuideForm,
})

to

return render(request,'hsguides/guide_create.html', {
    'DeckForm': DeckForm,
    'GuideForm': GuideForm,
})

Upvotes: 2

Shang Wang
Shang Wang

Reputation: 25559

Try this, you might forgot to pass the RequestContext:

from django.template import RequestContext

return render_to_response('hsguides/guide_create.html', 
                          {'DeckForm': DeckForm, 'GuideForm': GuideForm},
                          RequestContext(request))

It passes the csrf token to the template.

Upvotes: 1

doniyor
doniyor

Reputation: 37934

I didnot check the whole thing, but this place is wrong, it should be:

if request.method == "POST":
    deck = DeckForm(request.POST)
    if deck.is_valid():
        # ....

you are not packing the POST data into your forms..

the same goes for the second form as well

Upvotes: 1

Related Questions