Django Tutorial User Input with Forms

Requirements

This tutorial extends from the Docker Compose for Django tutorial. It is possible to follow along without creating the docker containers, however, I will leave it up to the reader to setup their environment to match this tutorial.

Goals

By the end of this tutorial you will learn how to create a django application that enables users to provide information which will be stored in the database. You will learn about Django models and Django forms. 

Steps

  • CD into the dockerdjango directory and make a new directory named apps and CD into the apps directory.
  • Extend this directory so that you have the following files (leave them as empty files for the time being but make sure they are the same format).
apps
├── __init__.py
└── data_entry
    ├── __init__.py
    ├── admin.py
    ├── choices.py
    ├── forms.py
    ├── models.py
    ├── templates
    │   ├── _base.html
    │   └── index.html
    ├── urls.py
    ├── views.py

  • modify the dockerdjango/urls.py file to include the urls from dockerdjango.apps.data_entry app. Add the following line into the urlpatterns list.

url(r'^', include('dockerdjango.apps.data_entry.urls')),

  • Modify the settings.py file by adding the STATIC_ROOT variable as follows:

STATIC_ROOT = os.path.join(BASE_DIR,'static')

  • Modfiy the models.py file within the data_entry app. This is where we define what models that will be stored in the database. This is where the input from our apps user will be stored and we will define what fields the user will need to provide in the models.py file.
from django.db import models
import choices
class DataRow(models.Model):
    date = models.DateField(blank=False)
    gender = models.CharField(max_length = 1, choices = choices.GENDER_CHOICES, blank=False)
    favorite_number = models.IntegerField(blank=False)
  • You will notive that the gender field in the DataRow model will take the value chosen by the user that is defined in the choices.GENDER_CHOICES variable. We will next define this list.
  • Modify the choices.py file and include the following:

GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)

  • Next step is to define the form that the user will populate on the app. Django has a form functionality that we will make use of that simplifies the process of getting input from users. Modify the forms.py file so that it looks like the following:
from django import forms
import choices
import datetime
class DataRowForm(forms.Form):
    date = forms.DateField(initial=datetime.date.today)
    gender = forms.ChoiceField(choices = choices.GENDER_CHOICES)
    favorite_number = forms.IntegerField()

Notice that the choices.GENDER_CHOICES field is referenced in the gender field of the DataRowForm object. This is because for this app we need to restrict the options the user can provide by passing through a choices parameter. This ensures that when filling the form the user can only choose either 'Male' or 'Female' (note that this restriction is also enforced in the DataRow object in models.py). By restricting the choices that the user can choose it makes analyzing the data more easy as we will know for certain that there will only be 2 options instead of having to worry about various entries the user may have manually entered.

  • Next we will update the dockerdjango/apps/data_entry/urls.py file so that the app knows what to do when a user goes to a particular URL. Include the following code into the urls.py file.
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]

The url(r'^$', views.index, name='index') means that when the user visits the root directory of the website the index function within views should be called. The name parameter is a way to identify the URL which is usefule if one needs to access the URL once in its final form.

  • The next step is to define the view function in order to handle user input and to pass data from the backend to the front end. In simple terms the views.py function is a python script that takes a Web Request as input and outputs a Web Response. For this tutorial the views.py file is quite simple. It checks if the request is of type POST, if it is then create a new entry into the database by extracting the data contained in the request object that the user of the app provided, once this has been done then return the user back to the same page with the updated input. Otherwise create a new form that the user will fill out. In addition it extracts all the rows from the DataRow table in the database as well as counts the number of rows to be passed into the index.html template.

 

from django.shortcuts import render, redirect
from .models import DataRow
from .forms import DataRowForm
def index(request):
if request.method == 'POST':
form = DataRowForm(request.POST)
if form.is_valid():
DataRow.objects.create(date=request.POST['date'], gender = request.POST['gender'], favorite_number = request.POST['favorite_number'])
return redirect('/')
else:
form = DataRowForm()
datarows=DataRow.objects.all()
count = DataRow.objects.count()
return render(request, 'index.html', {'data_row':datarows, 'count':count, 'form':form})

Next we will need to create the html template that will render the website as well as the data that is parsed through.

  • The _base.html file will form the foundation of our app. Generally any child pages will extend the _base.html file. For this tutorial it will make use of the bootstrap framework. Explaining about bootstrap is beyond the scope of this tutorial, however, there are plenty of resources that can be found online such as here. Your _base.html file should look like the following:
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
<title>Docker Compose Django Tutorial</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" />
<link rel=="stylesheet" href="{% static "css/main.css" %}" />
</head>
<body>
<div class="container">
{% block content %}
{% endblock %}
</div>
<script src = "//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>

Please note the use of {% load staticfiles %} and {% static "css/main.css" %}. These tags means that the template should refer to scripts that are located in the static directory (defined earlier in the settings.py file).

  • Next we will update the index.html file that contains the count of the number of entries users have entered to the site. It also contains the form that we defined earlier that users can populate and submit. Finally, it also present a list of all entries that have been submitted from all users of the website. 
{% extends "_base.html" %}
{% block content %}
{% load staticfiles %}
<div class="text-center">
<p>
There has been <strong>{{count}}</strong> entries.
</p>
</div>
<br />
<form action="/" method="POST">
{% csrf_token %}
{{form}}
<input type="submit" class="btn btn-primary btn-lg btn-block" value="Enter">
</form>
<br />
<hr />
<div>
{% for data in data_row %}
<h4 class="well"><em>{{data.date}}</em> - <strong>{{data.gender}}</strong> - <strong>{{data.favorite_number}}</strong></h4>
{% endfor %}
</div>
{% endblock content %}

The csrf_token protects the website from cross site request forgeries. This is security to protect against malicious hardware from interacting on the website and imitating a logged in user of the site.

  • Next we will need to include a css file in the static directory that will be referenced in the html templates. Navigate to the root of your directory (tutorial directory if you were following from the Docker Compose for Django tutorial). Create a static directory and inside it make a file with the relative file path css/main.css. Enter the following into the file:
.container{
max_width: 500px;
position: relative;
}
  • Finally you will need to get a bash terminal into the web container and run the following commands:
    • python manage.py makemigrations data_entry.
    • python manage.py migrate
    • python manage.py collectstatic
  • When you navigate to the web container's IP address on your local machine on port 8000 you should see something like the following:

Conclusion

Now you have successfully made a django app on Docker (hopefully) that enables users to provide input. Try entering some input into the form and see what happens. Next we will have a look at building a RESTful API to enable data access of the user inputs. Go here to learn more.

Check out the youtube video below to see a demonstration of how the app should look like as well as learn some useful Docker commands.

Subscribe to our mailing list

* indicates required