I'm facing some difficulties while trying to create a new user using UserCreationForm in Django.
I think that the issue is on the signup HTML page, but I can't really understand what am I doing wrong.
When I click submit after filling the required fields nothing happens.
I hope you could help me out.
Part of signup.html:
<div class="container">
<form id="register-form" method="post">
{% csrf_token %}
{% for field in form %}
{% if field.name == 'first_name' %}
<div class="form-group">
<input id="register-first_name" type="text" name="registerFirst" required
class="input-material">
<label for="register-first_name" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'last_name' %}
<div class="form-group">
<input id="register-last_name" type="text" name="registerLast" required
class="input-material">
<label for="register-last_name" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'username' %}
<div class="form-group">
<input id="username" type="text" name="username" required
class="input-material">
<label for="username" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'email' %}
<div class="form-group">
<input id="register-email" type="text" name="registerEmail" required
class="input-material">
<label for="register-email" class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% if field.name == 'password' %}
<div class="form-group">
<input id={{ form.name.name }} type="text" name="password" required
class="input-material">
<label for={{ form.name.name }} class="label-material">{{ field.label_tag }}</label>
</div>
{% endif %}
{% endfor %}
<input id="register" type="submit" value="Register" class="btn btn-primary">
</form>
<div/>
my forms.py:
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
first_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
last_name = forms.CharField(max_length=30, required=False, help_text='Optional.')
email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password', )
def save(self, commit=True):
user = super(SignUpForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
my views.py:
from django.http import HttpResponse
from django.shortcuts import render
from django.contrib.auth import authenticate
from django.contrib.auth import login as login_a
from django.shortcuts import render, redirect
from movie.forms import SignUpForm
def index(request):
return render(request, 'home.html')
def login(request):
return render(request,'login.html')
def logout(request):
return render(request,'logout.html')
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password')
print (username);
print (raw_password);
user = authenticate(username=username, password=raw_password)
login_a(request, user)
return redirect('login')
else:
form = SignUpForm()
return render(request, 'signup.html', {'form': form})
Your form looks incorrect. You are using incorrect values for the names (e.g. name="registerFirst" instead of name="first_name"), so the Django form will not use the submitted values. Then you are not displaying the field errors, so you don't get any useful feedback when you submit the form.
I would start by letting Django render the form. That will let you fix any problems in the view.
<form id="register-form" method="post">
{% csrf_token %}
{{ form.as_p }}
<input id="register" type="submit" value="Register" class="btn btn-primary">
</form>
To help debugging, you can print values in your view, for example add print(form.errors) after the if form.is_valid(): block.
Then, once the view is working with the simple template, you can render the fields manually if you need more control over the layout. See the docs on rendering fields manually for more info. If you do this, remember to display any field/form errors to the user.
If you do render the fields manually, you can access the fields with {{ form.first_name }}, instead of looping through {% for field in form %} then having to check field.name.
Related
I have created an HTMl register form template, and designed it such that if there is any validation error, it outputs the error and that works fine. Register form showing "passwords do not match" error The problem I'm having is the whole form fields clear once I hit submit and the errors show up, this was if a user has a "passwords do not match error" he'd have to input all his details from scratch. I want the user to input only the fields that has errors.
The register HTML form
<form method="POST" class="requires-validation" novalidate>
{% csrf_token %}
<div class="col-md-12">
<input class="form-control" type="text" name="first_name" placeholder="Firstname" required>
{% if form.first_name.errors %}
{% for error in form.first_name.errors %}
<span style="color:#DC3545;">
{{error}}
</span>
{% endfor %}
{% endif %}
</div>
<div class="col-md-12">
<input class="form-control" type="text" name="last_name" placeholder="Lastname" required>
{% if form.last_name.errors %}
{% for error in form.last_name.errors %}
<span style="color:#DC3545;">
{{error}}
</span>
{% endfor %}
{% endif %}
</div>
<div class="col-md-12">
<input class="form-control" type="text" name="email" placeholder="Email address" required>
{% if form.email.errors %}
{% for error in form.email.errors %}
<span style="color:#DC3545;">
{{error}}
</span>
{% endfor %}
{% endif %}
</div>
<div class="col-md-12">
<input class="form-control" type="password" name="password1" placeholder="Enter Password" required>
{% if form.password1.errors %}
{% for error in form.password1.errors %}
<span style="color:#DC3545;">
{{error}}
</span>
{% endfor %}
{% endif %}
</div>
<div class="col-md-12">
<input class="form-control" type="password" name="password2" placeholder="Confirm your password" required>
{% if form.password2.errors %}
{% for error in form.password2.errors %}
<span style="color:#DC3545;">
Passwords do not match, confirm and try again
</span>
{% endfor %}
{% endif %}
</div>
<div class="form-button mt-3">
<button id="submit" type="submit" class="btn btn-primary">Register</button>
</div>
<br>
<span>Already have an account? Sign in</span>
</form>
The views.py for register form
def register_view(request):
form = CustomUserCreationForm()
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
messages.success(request, f'{user.first_name}, your account has been created succesfully')
return redirect('home')
else:
messages.error(request, form.errors)
return render(request, 'base/register.html', {'form' : form })
The Register form model
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import UserModel
from django import forms
class CustomUserCreationForm(UserCreationForm):
first_name = forms.CharField(
label='',
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder':'Firstname'})
)
last_name = forms.CharField(
label='',
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder':'Lastname'})
)
email = forms.CharField(
label='',
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder':'Email'})
)
password1 = forms.CharField(
label='',
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder':'Enter Password'})
)
password2 = forms.CharField(
label='',
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder':'Enter Password again'})
)
class Meta:
model = UserModel
fields = ('email','first_name','last_name')
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = UserModel
fields = ('email','first_name','last_name')
I have fixed this issue, the problem is that I was rendering the form fields with <Input....> tag instead of rendering them using the Jinja tags i.e {{form.field}}
==== models.py ====
class EmployeeModel(models.Model):
name = models.CharField(max_length=255)
email = models.EmailField()
def __str__(self):
return self.name
==== forms.py ====
class EmployeeForm(forms.ModelForm):
class Meta:
model = EmployeeModel
fields = "__all__"
widgets = {
'name':forms.TextInput(attrs={'placeholder':'Enter Employee Name'}),
'email':forms.EmailInput(attrs={'placeholder':'Enter Employee E-Mail'}),
}
==== views.py ====
def EmployeeView(request):
if request.method == "POST":
form = EmployeeForm(request.POST)
if form.is_valid():
print("======= form is validated ============")
form.save()
messages.info(request,'Employee Added')
return redirect("/")
else:
print("======= form is not validated ============")
context= {'form':form}
return render(request,'index.html',context)
else:
form = EmployeeForm()
context= {'form':form}
return render(request,'index.html',context)
==== html code =====
{% block body %}
<div>
{% if messages %}
{% for msg in messages %}
{{msg}}
{% endfor %}
{% endif %}
</div>
<br>
<form action="" method="POST" novalidate >
{% csrf_token %}
<p>{{form.name.label}}:{{form.name}} {{form.name.errors|striptags}} </p>
<p>{{form.email.label}}:{{form.email}} {{form.email.errors|striptags}} </p>
<p><button type="submit">Add</button></p>
</form>
{% endblock body %}
===== output ========
I have Tried some patterns which are suggested by some Stackoverflow users. They are like : date:'jS M Y' & date:'c' But not working in my case.
Also referred this article : django update view not showing date input (previous) values
Models.py
from tkinter import CASCADE
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
# Create your models here.
class Ticket2(models.Model):
ticketholder = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
ticket_id = models.CharField(max_length=8, default='NS000001')
server_details = models.CharField(max_length=100)
send_date = models.DateTimeField(default=timezone.now)
license_no = models.CharField(max_length=25)
file = models.FileField(upload_to='documents/%Y%m%d/')
def __str__(self):
return self.ticket_id
edit.html
{% extends 'base.html' %}
{% block content %}
<h3 class="row justify-content-around">Edit Form</h3>
<div class="row justify-content-around" class="modal-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="form-group">
<label for="exampleInputEmail1">Ticket ID</label>
<input type="text" value="{{ticketdata.ticket_id}}" name="ticket_id" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Server Details</label>
<input type="text" value="{{ticketdata.server_details}}" name="server_details" class="form-control" id="exampleInputPassword1" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Send Date</label>
<input type="datetime-local" value="{{ ticketdata.send_date.value|date:'jS M Y' }}" name="send_date" class="form-control" id="exampleInputPassword1" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">License No</label>
<input type="text" value="{{ticketdata.license_no}}" name="license_no" class="form-control" id="exampleInputPassword1" required>
</div>
<div class="form-group">
<label for="exampleInputPassword1">Files</label>
<input type="file" value="{{ticketdata.file}}" name="file" class="form-control" id="exampleInputPassword1" required>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</form>
</div>
{% endblock %}
views.py
from django.shortcuts import render, redirect
from .models import Ticket2
from tmsapp.forms import SaveTicket
from django.contrib import messages
from django.contrib.auth.decorators import login_required
# Create your views here.
#login_required
def Index(request):
ticketdata = Ticket2.objects.filter(ticketholder = request.user)
if request.method == "POST":
form = SaveTicket(request.POST,request.FILES or None)
if form.is_valid():
form.save(commit=False).ticketholder = request.user
form.save()
messages.success(request,("Data has been added successfully !!"))
print(form)
return redirect('index')
else:
form = SaveTicket()
return render(request, 'index.html', {'ticketdata':ticketdata})
#login_required
def Delete(request, id):
ticketdata = Ticket2.objects.get(pk=id)
ticketdata.delete()
messages.success(request,("Data has been deleted successfully !!"))
return redirect('index')
#login_required
def Edit(request, id):
if request.method == "POST":
ticketdata = Ticket2.objects.get(pk=id)
form = SaveTicket(request.POST,request.FILES or None, instance=ticketdata)
if form.is_valid():
form.save()
messages.success(request,("Data has been updated successfully !!"))
print(form)
return redirect('index')
else:
ticketdata = Ticket2.objects.get(pk=id)
print(ticketdata.file)
return render(request, 'edit.html', {'ticketdata':ticketdata})
I was having a problem with send data like(username, password) to the Django administration so after several tries I found I very simple fixes, which I will put it here.
First My Html Source:
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
<br>
<input placeholder="username" type="text" name="username"><br>
<br><input placeholder="Password" type="password" name="password">
<br><input type="submit" value="save">
</form>
{% endblock content %}
Second My models.py file :
from django.db import models
class Login(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=50)
Third And the important important thing and here You will get the fix GO TO VIWES.py
from django.shortcuts import render
from .models import Login
def Test(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
form = Login(username=username, password=password)
form.save()
return render(request, 'pages/about.html', )
return should be out of (if)
I have multiple fields in my Django UserCreationForm including the already included username, password 1, and password 2. I have also added and email field. I am unable to add a checkbox.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
I want there to be a checkbox to declare if the user wants to register as a teacher or as a student.
{% extends 'base.html' %}
{% block content %}
<div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
</form>
</div>
{% endblock %}
from django.shortcuts import render, redirect
from .forms import UserRegisterForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
if request.method == "POST":
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}!')
return redirect('/')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
return render(request, 'users/profile.html')
You already added the BooleanField in django form here:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
is_teacher = forms.BooleanField(required=True)
class Meta:
model = User
fields = ['is_teacher', 'username', 'email', 'password1', 'password2']
looks good you only need to add the it to your html
{% extends 'base.html' %}
{% block content %} <div class="container row">
<form method="POST" class='input-field col s6 offset-s3' >
{% csrf_token %}
<fieldset>
<legend>
Sign Up:
</legend>
{{form.as_p}}
</fieldset>
<br>
<button class="btn waves-effect waves-light green accent-2" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
<br><br>
<div>
<small>
Already have an account? <a href='{% url "login"%}'>Sign In</a>
</small>
</div>
<div name="new is teacher checkbox">
{{form.is_teacher}}
</div>
</form>
</div> {% endblock %}
You can access the value of is_teacher in views too by forms.cleaned_data.get('is_teacher')
I'm getting confused as to how to show the ValidationError in my signup page whenever password and password confirmation are not the same instead of sending me to a page that says ValueError and stuffs. However, when I got to the admin, it definitely shows the ValidationError. Any help? Here's my code
forms.py
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
` from django.core import validators
class AccountForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ("username", "email", "password1", "password2")
# def save(self, commit=True):
# user = super(AccountForm, self).save(commit=False)
# user.email = self.cleaned_data["email"]
# if commit:
# user.save()
# return user
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if not password2:
raise forms.ValidationError(
self.error_messages['Must input Password Confirmation'],
code='Password_Confirmation_empty')
if password1 != password2:
raise forms.ValidationError(
self.error_messages['Passwords do not match.'],
code='password_mismatch')
password_validation.validate_password(
self.cleaned_data.get('password2'), self.instance)
return password2
def save(self, commit=True):
user = super(AccountForm,self).save(commit=False)
user.email = self.cleaned_data["email"]
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
views.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import *
from django.contrib import messages
from django.core import validators
def signup(request):
if request.method == 'POST':
form = AccountForm(request.POST)
# form = UserCreationForm(request.POST)
if form.is_valid:
username = request.POST.get("username")
email = request.POST.get("email")
password1 = request.POST.get("password1")
password2 = request.POST.get("password2")
# form.clean_password2()
form.save()
return HttpResponseRedirect('/login/')
else:
form = AccountForm()
# form = UserCreationForm()
return render(request, 'accounts/signup.html', {'form':form})
signup.html
{% extends "base_accounts.html" %}
{% load staticfiles %}
{% block content %}
<div class="row">
<div class="col-md-6 col-md-offset-3 text-center">
<h2>JCREL INVENTORY</h2>
</div>
</div>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default">
<div class="panel-heading">Register</div>
<div class="panel-body">
<form action="/signup/" class="form" method="POST">
{% csrf_token %}
{% if form.errors %}
{% for field in form %}
{{field.ValidationError}}
{% endfor %}
{% endif %}
<!-- {{ form.as_p }} -->
<div class="form-group">
<label>Username</label>
<input name="username" type="text"
class="form-control" required autofocus>
</div>
<div class="form-group">
<label>Email</label>
<input name="email" type="text"
class="form-control" required autofocus>
</div>
<div class="form-group">
<label>Password</label>
<!-- {{ form.ValidationError }} -->
<input name="password1"
type="password" id="inputPassword"
class="form-control" required>
</div>
<div class="form-group">
<label>Confirm Password</label>
<!-- {{ form.ValidationError }} -->
<input name="password2" type="password"
id="inputPassword" class="form-control" required>
</div>
<!-- {{form}} -->
<div class="form-group">
<input type="submit"
class="form-control btn btn-primary btn-block"
value="Sign Up" />
<input type="hidden" name="next" value="{{ next }}" />
</div>
<div class="form-group">
<hr>
<p>Already have an account?</p>
Login
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
Whenever there are errors in the form you can access the list of them (within a view) through name_of_the_form.errors (in you case it will be form.errors). Then, you can iterate over this list and print out the message property (e.g. error.message)