Django Forms

Part of this chapter is based on tutorials by Django Girls Tutorial : https://tutorial.djangogirls.org

The final thing we want to do on our website is create a nice way to add and edit blog posts. Django's admin is cool, but it is rather hard to customize and make pretty. With forms we will have absolute power over our interface – we can do almost anything we can imagine!

The nice thing about Django forms is that we can either define one from scratch or create a ModelForm which will save the result of the form to the model.

This is exactly what we want to do: we will create a form for our Player model.

Like every important part of Django, forms have their own file: forms.py.

We need to create a file with this name in the myfirstgame directory.

myfirstgame
   └── forms.py

OK, let's open it and type the following code:

from django import forms

from .models import Player

class PlayerForm(forms.ModelForm):

    class Meta:
        model = Player
        fields = ('name',)

We need to import Django forms first (from django import forms) and, obviously, our Post model (from .models import Post).

PlayerForm, as you probably suspect, is the name of our form. We need to tell Django that this form is a ModelForm (so Django will do some magic for us) – forms.ModelForm is responsible for that.

Next, we have class Meta, where we tell Django which model should be used to create this form (model = Player).

Finally, we can say which field(s) should end up in our form. In this scenario we want only name to be exposed.

And that's it! All we need to do now is use the form in a view and display it in a template.

So once again we will create a link to the page, a URL, a view and a template.

Adding form to the web page

Open myfirstgame/templates/myfirstgame/index.html file.

You will be adding the following piece of code:

<form method="POST" class="player-form">{% csrf_token %}
        {{ form.as_p }}
        <button type="submit" class="save btn btn-default">Submit</button>
</form>

The final code in the index.html file should look like the following:

{% extends 'myfirstgame/base.html' %}

{% block content %}
<div class="content container">
    <div class="row">
        <div class="col-md-12">
            <h2>Come back soon when we add more functionality</h2>
            <p>This is a <em>choose your own adventure game</em>.</p>

            <form method="POST" class="player-form">{% csrf_token %}
                {{ form.as_p }}
                <button type="submit" class="save btn btn-default">Submit</button>
            </form>
        </div>
    </div>
    <div class="row">
        <div class="col-md-12">
            <h3 id="player-listings">List of players in order of latest who played</h3>
            <ul class="player-list">
            {% for player in players %}
                <li><span class="player">{{ player.name }}</span> - Game Over on <em>{{ player.game_end }}</em></li>
            {% endfor %}
            </ul>
        </div>
    </div>
</div>
{% endblock %}

Now open myfirstgame/views.py and add the following lines at the top of the file:

from .forms import PlayerForm

Then add the following:

form = PlayerForm()

This will create the Player form called form and is returned and rendered when you load the webpage.

The final code should look like this in views.py:

from django.shortcuts import render
from django.utils import timezone

from .forms import PlayerForm
from .models import Player

def index(request):  
    form = PlayerForm()
    players = Player.objects.filter(game_end__lte=timezone.now()).order_by("game_end")
    return render(request, 'myfirstgame/index.html', {'form':form, 'players':players})

Save the views.py file. Go to http://127.0.0.1:8000 and you will see the following:

But, wait a minute! When you type something in the name fields and try to save it, what will happen?

Nothing! We are once again on the same page and our text is gone… and no new post is added. So what went wrong?

The answer is: nothing. We need to do a little bit more work in our view.

Saving the form

Open myfirstgame/views.py once again.

When we submit the form, we are brought back to the same view, but this time we have some more data in request, more specifically in request.POST (the naming has nothing to do with a blog "post"; it's to do with the fact that we're "posting" data).

Remember how in the HTML file, our <form> definition had the variable method="POST"? All the fields from the form are now in request.POST. You should not rename POST to anything else (the only other valid value for method is GET, but we have no time to explain what the difference is).

So in our view we have two separate situations to handle: first, when we access the page for the first time and we want a blank form, and second, when we go back to the view with all form data we just typed. So we need to add a condition (we will use if for that):

if request.method == "POST":
    [...]
else:
    form = PostForm()

It's time to fill in the dots [...]. If methodis POSTthen we want to construct the PlayerForm with data from the form, right? We will do that as follows:

form = PostForm(request.POST)

The next thing is to check if the form is correct (all required fields are set and no incorrect values have been submitted). We do that with form.is_valid().

We check if the form is valid and if so, we can save it!

if form.is_valid():
    player = form.save()
    post.save()

Basically, we have two things here:

  • we save the form with form.save and we add a player.
  • form.save() - Save to Player model.
  • post.save() will preserve changes and a new player entry is created!

OK, we've talked a lot, but we probably want to see what the whole _view _looks like now, right?

from django.shortcuts import render
from django.utils import timezone

from .forms import PlayerForm
from .models import Player

def index(request):  

    players = Player.objects.filter(game_end__lte=timezone.now()).order_by("game_end")

    if request.method == "POST":
        form = PlayerForm(request.POST)
        if form.is_valid():
            player = form.save()
            player.save()
    else:
        form = PlayerForm()

    return render(request, 'myfirstgame/index.html', {'form':form, 'players':players})

Save the views.py file. Go to http://127.0.0.1:8000 and add a name:

When you submitted the name, to see if it's added, go to http://127.0.0.1:8000/admin and you can see the entry saved to the database:

Now we have the basics of using Forms to create new players. Our next step is to re-direct the player to another page welcoming them and start the text-based adventure game.

results matching ""

    No results matching ""