Home > Back-end >  Customize Form with Django FORM API
Customize Form with Django FORM API

Time:05-02

I am currently creating an register/login form with the Django framework, since I am new to this framework, I don't know much about the FORM API.

I am not using the FORM API, since I don't know if I can customize it. Is there any way to use my styling with the FORM API? As the state of now, I am just creating my own one, without using the API, but since the FORM API is more secure and much faster to set up for user creation, I would like to use it.

So my question is, can I implement custom styling with the FORM API? Including <input>,<div> etc..

Here is my HTML form:

{% if messages %}
<ul >
    {% for message in messages %}
    <li{% if message.tags %} {% endif %}>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}

    <div >
        <div  style="background:black;">
            <div >
                <form   method='POST' action="{% url 'users:register' %}" >
                    {% csrf_token %}
                    <span >
                        <i ></i>
                    </span>
                    <span >
                        Register
                    </span>
                    <div  data-validate = "Enter username">
                        <input  type="text" name="username" placeholder="Username" required>
                        <span  data-placeholder="&#xf207;"></span>
                    </div>
                    <div  data-validate="Enter password">
                        <input  type="password" name="pass" placeholder="Password" required>
                        <span  data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div  data-validate="Confirm password">
                        <input  type="password" name="pass-confirm" placeholder="Confirm Password" required>
                        <span  data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div  data-validate="Enter Email">
                        <input  type="email" name="mail" placeholder="E-Mail" required>
                        <span  data-placeholder="&#xf191;"></span>
                    </div>
    
                    <div >
                        <button  type="submit" name="submit" value="submit">
                            Register
                        </button>
                    </div>
    
                    <div >
                        <a  href="login">
                            Already registered?
                        </a>
                    </div>
    
                </form>
            </div>
        </div>
    </div>

Here is my views.py backend:

def register(request):
    if request.method == "POST":
        username = request.POST["username"]
        password = request.POST["pass"]
        password_confirm = request.POST["pass-confirm"]
        email = request.POST["mail"]
        submit = request.POST["submit"]
        
        
        print("UserName : ", username)
        print('Email : ', email)
        print('Password : ', password)
        print('Password Confirm : ', password_confirm)
        
        SpecialSym =['$', '@', '#', '%', '?']
        confirm = False
        
        if request.POST.get("submit"):
            if len(username) < 7:
                
                print('Username must be more than 10 char.')
                confirm = False
                messages.error(request, "Username must be more than 10 char.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(username) > 15:
          
                print('Username must be less than 15 char.')
                confirm = False
                messages.error(request, "Username must be less than 15 char.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if any(char in SpecialSym for char in username):
                print('Username can\'t contain special characters.')
                confirm = False
                messages.error(request, "Username can't contain special characters", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(password) < 8:
                print("Your password is too short")
                confirm = False
                messages.error(request, "Your password is too short.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if len(password) > 25:
                print("Your password must be less than 25 char")
                confirm = False
                messages.error(request, "Your password must be less than 25 char.", 'red')
                return HttpResponseRedirect(reverse('users:register')) 
            
            if not any(char.isdigit() for char in password):
                print('Password should have at least one numeral')
                confirm = False
                messages.error(request, "Your password should have at least one numeral ", 'red')
                return HttpResponseRedirect(reverse('users:register'))

            if not any(char.isupper() for char in password):
                print('Password should have at least one uppercase letter')
                confirm = False
                messages.error(request, "Your password should have at least one uppercase letter ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                
            if not any(char.islower() for char in password):
                print('Password should have at least one lowercase letter')
                confirm = False
                messages.error(request, "Your password should have at least one lowercase letter ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                        
            if not any(char in SpecialSym for char in password):
                print('Password should have at least one of the symbols $@#?')
                confirm = False
                messages.error(request, "Your password should have at least one of these symbols: $@#? ", 'red')
                return HttpResponseRedirect(reverse('users:register'))
            
            if (password != password_confirm):
                print("Passwords don't match")
                confirm = False
                messages.error(request, "Passwords don't match.", 'red')
                return HttpResponseRedirect(reverse('users:register'))
                
            if confirm == True:
                
                messages.success(request, "Success! form submitted.", 'green')
                return HttpResponseRedirect(reverse('users:register'))
                
                
    return render(request, 'users/register.html')

CodePudding user response:

You can use in-built UserCreationForm[django-doc], which is at the path from django.contrib.auth.forms import UserCreationForm.

Now, as your current code, you don't need to use messages framework, as the in-built Form has already many validations, you have done.

In your code you can implement in following way, simply do this:

I am providing only a minimal reproducible example,as you have many css classes in the templates so I only add my_class to every field, you can add your own class, you can see it with Ctrl U or page source.

urls.py

from django.urls import path
from . import views
app_name = 'users'
urlpatterns = [
    path('', views.register, name='home'),
    path('success/', views.success, name='success')
]

views.py

from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.contrib.auth.models import User
from django.contrib.auth.hashers import make_password
from django.urls import reverse

from home.forms import MyUserCreationForm


def register(request):
    if request.method == 'POST':
        form = MyUserCreationForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['username']
            password1 = form.cleaned_data['password1']
            email = form.cleaned_data['email']
            user_data = User(username=username,
                             password=make_password(password1), email=email)

            user_data.save()
            return HttpResponseRedirect(reverse('users:success'))
    else:
        form = MyUserCreationForm()
    return render(request, 'users/register.html', {'form': form})


def success(request):
    return render(request, 'users/thanks.html')

forms.py

from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth import password_validation

from django.utils.translation import gettext, gettext_lazy as _
from django.contrib.auth.models import User


class MyUserCreationForm(UserCreationForm):
    password1 = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(
            attrs={'autocomplete': 'new-password', 'class': 'my_class', 'placeholder': 'password'}),
        help_text=password_validation.password_validators_help_text_html(),
        error_messages={'required': 'password is required'}
    )
    password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput(
            attrs={'autocomplete': 'new-password', 'class': 'my_class', 'placeholder': 'confirm password'}),
        strip=False,
        help_text=_("Enter the same password as before, for verification."),
        error_messages={'required': 'password confirm is required'}
    )
    email = forms.CharField(widget=forms.EmailInput(
        attrs={'class': 'my_class', 'placeholder': 'Email'}), error_messages={'required': 'Email is required'})

    class Meta:
        model = User
        fields = ['username', 'email']
        error_messages = {
            'username': {'required': 'Username is required'},
        }
        widgets = {
            'username': forms.TextInput(attrs={'class': 'myclass', 'placeholder': 'Username'}),
        }

Note: you can use any class in any field, you can change here for every field attrs={'class': 'my_class'), I have used my_class in every field just for example, you can view it in page source.

Note: The example might be a bit complex, since I have inherited and changed the django's inbuilt form for adding css classes.

register.html or template file

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .red{
            color:red;
            font-size:1.15rem;
        }
    </style>
</head>
<body>
    {% if form %}
    <form method="POST" novalidate>
        {% csrf_token %}
        {% if form.non_field_errors %}
        {% for error in form.non_field_errors %}
        <div >
            <p>{{error}}</p>
        </div>
        {% endfor %}
        {% endif %}

        {% for field in form %}
        <div>
            {{field.label_tag}} {{field}}
            <br>
            {% for error in field.errors  %}
                <div >
                    <span>{{error}}</span>
                </div>
            {% endfor %}
        </div>
        {% endfor %}
        <input type="submit" value="Save">
    </form>
    {% else %}
    <p>There is some error, form does not come from view.</p>
    {% endif %}
</body>
</html>

thanks.html (which will be used for redirection after successfully submitting the form)

<body>
    <h2>You are now a user! logged in !</h2>
</body>

Through this example, your data successfully saved in the database, you can see it by creating superuser, through python manage.py createsuperuser and by logged in into the admin site, in the Users table.

The above work can become more easy with class based authentication views[django-doc].

  • Related