Forms Django

Notes Single

For this post we will create a Django project called "my_project", and app called "my_app", in app's views we will create a function called "index" tied to "my_app/" url. When the server receive a GET request will render a HTML file called "index.html" and when receive a POST request will render a HTML file called "user.html" sending as context the data received from "index.html".

"index.html" has a form with for send user data, including a photo to upload to the server.

Let's get started!

NOT using Django's Form class

Create the project "my_project" and the app "my_app"

We assume you has set a virtual environment and installed Django.

(env) path-to-the-project>django-admin startproject my_project
(env) path-to-the-project/my_project>py manage.py startapp my_app

Create the app's view

from django.shortcuts import render

def index(request):
    if request.method=="POST":
        # Handling the file uploaded
        # The file is stored at static/images
        file=request.FILES['photo']
        with open('static/images/'+file.name, 'wb+') as destination:
            for chunk in file.chunks():
                destination.write(chunk)
        # Case POST request: Load the user information page
        return render(request, 'my_app/user.html',
        # Context
        {
            "name":request.POST.get('name'),
            "username":request.POST.get('username'),
            "email":request.POST.get('email'),
            "photo":file.name,
        })
    # Case of GET request: Load the user registration form
    return render(request, 'my_app/index.html')

Register the app's url

from django.urls import path

from . import views

app_name = 'my_app' # namespace for app's urls
urlpatterns = [
    # path(url,function,name for this url)
    # ex: /my_app/
    path('', views.index, name='index')
]

Register the app's urls.py in project's urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('my_app/', include('my_app.urls')),
    path('admin/', admin.site.urls),
]

HTML templates

my_app/templates/my_app/index.html

<!DOCTYPE html>
<html>
<head>
    <title>User registration</title>
    <!-- Include Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <div class="row">
            <div class="col-md-8 col-lg-4">
                <h1>User registration</h1>
                <form class="" method="post" action="" enctype="multipart/form-data">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" class="form-control" id="name" name="name">
                    </div>
                    <div class="form-group">
                        <label for="username">Username:</label>
                        <input type="text" class="form-control" id="username" name="username">
                    </div>
                    <div class="form-group">
                        <label for="email">Email:</label>
                        <input type="email" class="form-control" id="email" name="email">
                    </div>
                    <div class="form-group">
                        <label for="photo">Photo:</label>
                        <input type="file" class="form-control-file" id="photo" name="photo">
                    </div>
                    <button type="submit" class="btn btn-primary">Submit</button>
                </form>
            </div>
        </div>
    </div>
    <!-- Include Bootstrap JS -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Notice the {% csrf_token %} instruction which injects in the form a hidden input that contains the CSRF token

my_app/templates/my_app/user.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>User information</title>
    <!-- Include Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <div class="row">
            <div class="col-md-8 col-lg-4">
                <h1>User information</h1>
                <form>
                    <div class="form-group">
                        <label for="name">Name:</label>
                        <input type="text" class="form-control" id="name" name="name" value="{{ name }}" disabled>
                    </div>
                    <div class="form-group">
                        <label for="username">Username:</label>
                        <input type="text" class="form-control" id="username" name="username" value="{{ username }}" disabled>
                    </div>
                    <div class="form-group">
                        <label for="email">Email:</label>
                        <input type="email" class="form-control" id="email" name="email" value="{{ email }}" disabled>
                    </div>
                    <div class="form-group">
                        <label for="photo">Photo:</label>
                        <img src="{% static 'images/' %}{{photo}}" class="img-fluid" alt="{{ photo }}">
                    </div>
                </form>
                <a href="{% url 'my_app:index'%}">Back</a>
            </div>
        </div>	
    </div>
    <!-- Include Bootstrap JS -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Update project's settings

At "my_project/settings.py" we must add the static dir for loading static files as the image in "user.html":

STATIC_URL = 'static/'
STATICFILES_DIRS = ['static']

Using Django's Form class

Django has a class that helps us to work with forms:

Create the form

At "my_app/forms.py":

from django import forms
from django.forms.widgets import TextInput, EmailInput, ClearableFileInput

class UserForm(forms.Form):
    name = forms.CharField(max_length=255, widget=TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Name'}))
    username = forms.CharField(max_length=30, widget=TextInput(
        attrs={'class': 'form-control', 'placeholder': 'Username'}))
    email = forms.EmailField(widget=EmailInput(
        attrs={'class': 'form-control', 'placeholder': 'Email'}))
    photo = forms.ImageField(required=False, widget=ClearableFileInput(
        attrs={'class': 'form-control-file'}))

Implement the form in the view

from django.shortcuts import render
from .forms import UserForm

def index(request):

    if request.method=="POST":
        # Handling the file uploaded
        # The file is stored at static/images
        if request.FILES:
            file=request.FILES['photo']
            with open('static/images/'+file.name, 'wb+') as destination:
                for chunk in file.chunks():
                    destination.write(chunk)
        # Case POST request: Load the user information page
        form = UserForm(request.POST)
        # check whether it's valid:
        if form.is_valid():
            return render(request, 'my_app/user.html',{'form':form,'photo':file.name})
        return render(request, 'my_app/index.html',{'form':form})
    # Case of GET request: Load the user registration form
    form = UserForm()
    return render(request, 'my_app/index.html',{'form':form})

Adapt the HTML templates

my_app/templates/my_app/index.html

<!DOCTYPE html>
<html>
<head>
    <title>User registration</title>
    <!-- Include Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <div class="row">
            <div class="col-md-8 col-lg-4">
                <h1>User registration</h1>
                <form class="" method="post" action="" enctype="multipart/form-data">
                    {% csrf_token %}
                    <div class="form-group">
                        <label for="name">Name:</label>
                        {{ form.name }}
                    </div>
                    <div class="form-group">
                        <label for="username">Username:</label>
                        {{ form.username }}
                    </div>
                    <div class="form-group">
                        <label for="email">Email:</label>
                        {{ form.email }}
                    </div>
                    <div class="form-group">
                        <label for="photo">Photo:</label>
                        {{ form.photo }}
                    </div>
                    <button type="submit" class="btn btn-primary">Submit</button>
                </form>
            </div>
        </div>
    </div>
    <!-- Include Bootstrap JS -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

my_app/templates/my_app/user.html

{% load static %}
<!DOCTYPE html>
<html>
<head>
    <title>User information</title>
    <!-- Include Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
    <div class="container mt-5">
        <div class="row">
            <div class="col-md-8 col-lg-4">
                <h1>User information</h1>
                <form>
                    <div class="form-group">
                        <label for="name">Name:</label>
                        {{ form.name }}
                    </div>
                    <div class="form-group">
                        <label for="username">Username:</label>
                        {{ form.username }}
                    </div>
                    <div class="form-group">
                        <label for="email">Email:</label>
                        {{ form.email }}
                    </div>
                    <div class="form-group">
                        <label for="photo">Photo:</label>
                        <img src="{% static 'images/' %}{{photo}}" class="img-fluid" alt="{{ photo }}">
                    </div>
                </form>
                <a href="{% url 'my_app:index'%}">Back</a>
            </div>
        </div>	
    </div>
    <!-- Include Bootstrap JS -->
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>

Thanks for reading :)
I invite you to continue reading other entries and visiting us again soon.

Related Posts: