Django. POST request after reloading a page. Sign up form

Question:

When user enters incorrect data in form, he gets errors. If after that user reloads a page, he gets the same page, the same form with the same fields, errors. I don’t know why after reloading a page request is POST.

Every time after sending form, when I reload page with form I send a POST request.

views.py

from django.shortcuts import render
from django.shortcuts import render, redirect
from .forms import LogInForm, SignUpForm
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.hashers import make_password
from django.contrib.auth import authenticate, logout, login as auth_login
from django.contrib import messages
import os
import shutil
# Create your views here.


@login_required
def index(request):
    return render(request, 'index.html')


def login(request):
    logInForm = LogInForm()
    if request.method == 'POST':
        form = LogInForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(
                username=cd['username'], password=cd['password'])
            if user is not None:
                auth_login(request, user)
                return redirect("main")
            else:
                messages.error(request, "Invalid login or password")
                return redirect('login')
        else:
            form = LogInForm()
    else:
        return render(request, 'logIn.html', {"form": logInForm})


def signUp(request):

    def createFolder(username):
        toFolder = "jsons/" + username
        fromFolder = "scripts/"
        os.mkdir(toFolder)
        toFolder = "jsons/" + username + '/scripts'
        os.mkdir(toFolder)
        os.mkdir("jsons/" + username + "/messages")
        if (os.path.exists(fromFolder) and os.path.exists(toFolder)):
            for file in os.listdir(fromFolder):
                if os.path.isfile(os.path.join(fromFolder, file)):
                    shutil.copy(os.path.join(fromFolder, file),
                                os.path.join(toFolder, file))
                if os.path.isdir(os.path.join(fromFolder, file)):
                    os.system(f'rd /S /Q {toFolder}/{file}')
                    shutil.copytree(os.path.join(fromFolder, file),
                                    os.path.join(toFolder, file))
        with open(toFolder + '/config.ini', 'w') as file:
            file.write('[Telegram]n')
            file.write('[VK]n')
            file.write('[INST]n')
            file.write('[WA]n')

    signUpForm = SignUpForm()

    if (request.method == 'POST'):
        form = SignUpForm(request.POST)
        if (form.is_valid()):
            user = form.save(commit=False)
            user.password = make_password('password')
            user.save()
            auth_login(request, user)
            createFolder(user.username)
            return redirect("main")
        else:
            return render(request, 'signUp.html', {"form": form})
    else:
        return render(request, 'signUp.html', {"form": signUpForm})


def logout_view(request):
    logout(request)
    return redirect('login')


@login_required
def profile(request):
    current_user = request.user
    username = current_user.username
    email = current_user.email
    phoneNumber = current_user.phoneNumber
    content = {
        'username': username,
        'email': email,
        'phoneNumber': phoneNumber,
    }
    return render(request, 'profile.html', context=content)

forms.py

from django.forms import ModelForm
from django import forms
from .models import User

class LogInForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(
        attrs={'placeholder': 'Username', 'class': 'form-input'}), required=True)
    password = forms.CharField(widget=forms.PasswordInput(
        attrs={'placeholder': 'Password', 'class': 'form-input'}), required=True, min_length=8)


class SignUpForm(ModelForm):
    password = forms.CharField(label='Password', widget=forms.PasswordInput(
        attrs={"placeholder": "Password"}), min_length=8, required=True)
    password2 = forms.CharField(
        label='Confirm password', widget=forms.PasswordInput(attrs={"placeholder": "Confirm password"}), min_length=8, required=True)
    error_css_class = 'message-error'
    error_messages = {
        'password_mismatch': 'Passwords must match.',
    }
    class Meta:
        model = User
        fields = ('username', 'email', 'phoneNumber', 'password')
        widgets = {
            "username": forms.TextInput(
                attrs={
                    "placeholder": "Username"
                }
            ),
            "email": forms.TextInput(
                attrs={
                    "placeholder": "Email"
                }
            ),
            "phoneNumber": forms.TextInput(
                attrs={
                    "placeholder": "Phone number (with a country code) ",
                    "type": "tel",
                    "minlength": 12,
                    "maxlength": 12,
                },
            ),
        }

    def clean(self):
        cleaned_data = super(SignUpForm, self).clean()
        password = self.cleaned_data.get("password")
        confirm_password = self.cleaned_data.get("password2")
        if password and confirm_password:
            if password != confirm_password:
                self.add_error(None, "Passwords don't match")
        ifNums = False
        ifLets = False
        for letter in password:
            if letter.isalpha():
                ifLets = True
            if letter.isdigit():
                ifNums = True
            if ifNums == True and ifLets == True:
                break
        if ifNums == False or ifLets == False:
            self.add_error("password","Your password must contain at least one digit and one letter!")  
        return cleaned_data

signUp.html

<!DOCTYPE html>
{% load static %}
<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">
        <link rel="stylesheet" href="{% static "css/signUp.css" %}" />
        <title>Sign up</title>
    </head>
    <body>
        <div class="container">
            <form class="form" method="post" action="{% url 'signUp' %}">
                <h1 class="title">Sign up</h1>
                {% csrf_token %}
                {% for field in form %}
                    {{ field }}
                    {% if field.errors %}
                        {% for error in field.errors %}
                            <span class="message-error"> {{ error }} </span>
                        {% endfor %}
                    {% endif %}
                {% endfor %}
                {% if form.non_field_errors %}
                    {% for non_field_error in form.non_field_errors %}
                        <span class="message-error"> {{ non_field_error }} </span>
                    {% endfor %}
                {% endif %}
                <label for="confirm-valid" class="label-check">
                    <input type="checkbox" id="confirm-valid" required> I've checked the correctness of the entered data
                </label>
                <label for="confirm-agreement" class="label-check">
                    <input type="checkbox" id="confirm-agreement" required> I agree with the user agreement
                </label>
                <button class="form-button" type="submit">Sign up</button>
            </form>
        </div>
    </body>
</html>

models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, AbstractUser
# Create your models here.


class User(AbstractUser):
    username = models.CharField(max_length=100, unique=True, error_messages={
                                'unique': "This username has already been registered."})
    password = models.CharField(max_length=200, unique=False)
    email = models.EmailField(unique=True, error_messages={
                              'unique': "This email has already been registered."})
    phoneNumber = models.CharField(max_length=12, unique=True, error_messages={
                                   'unique': "This phone number has already been registered."})
    first_name = None
    last_name = None

I need my form to work this way:
User enters correct data – he goes to main page.
User enters incorrect data – he gets the form with errors, but after reloading the page, form have to be clean.

EDIT
signUp view

        signUpForm = SignUpForm()

        if (request.method == 'POST'):
            form = SignUpForm(request.POST)
            if (form.is_valid()):
                user = form.save(commit=False)
                user.password = make_password('password')
                user.save()
                auth_login(request, user)
                createFolder(user.username)
                return redirect("main")
            else:
                return redirect('signUp')
        return render(request, 'signUp.html', {"form": signUpForm})
    else:
        return redirect('main')

If I make sign up view like this, it works. But after reloading I get form without errors. How can I make it so that the form after reloading in this way will be with errors?

Asked By: kirin

||

Answers:

Yes it can be done, the form will be rendered as it is, if you don’t create a fresh form variable everytime.
remove the line SignUpForm=SignUpForm().

    if (request.method == 'POST'):
        form = SignUpForm(request.POST)
        if (form.is_valid()):
            user = form.save(commit=False)
            user.password = make_password('password')
            user.save()
            auth_login(request, user)
            createFolder(user.username)
            return redirect("main")
    else:
        form = SignUpForm()
    return render(request, 'signUp.html', {"form": form})

similarly, in login view,

    def login(request):
    if request.method == 'POST':
        form = LogInForm(request.POST)
        if form.is_valid():
            cd = form.cleaned_data
            user = authenticate(
                username=cd['username'], password=cd['password'])
            if user is not None:
                auth_login(request, user)
                return redirect("main")
            else:
                messages.error(request, "Invalid login or password")
    else:
        form = LogInForm()
    return render(request, 'logIn.html', {"form": form})
Answered By: azzam
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.