I have a SignUp form that interacts with Django's user model to create new users. If password fields match, the user is successfully created and logged in. If password fields do not match, the user is not created, so I guess validation is working. But somehow, a validation error message is not shown, the form page is just rendered again. When I go to Django's admin page, the error messages pop up there! Why is it not popping in my template?!
This is my form:
class SignUpForm(forms.ModelForm):
password = forms.CharField(max_length=20, required=True, widget=forms.TextInput(attrs={'placeholder':'Password', 'class':'form-control', 'type':'password'}),)
password2 = forms.CharField(max_length=20, required=True, widget=forms.TextInput(attrs={'placeholder':'Confirm Password', 'class':'form-control', 'type':'password'}),)
class Meta:
model = User
widgets = {'first_name': forms.TextInput(attrs={'placeholder':'First Name', 'class':'form-control'}),
'last_name': forms.TextInput(attrs={'placeholder':'Last Name', 'class':'form-control'}),
'email': forms.TextInput(attrs={'placeholder':'Email', 'class':'form-control', 'type':'email'}),
'username': forms.TextInput(attrs={'placeholder':'Username', 'class':'form-control'}),
'password': forms.TextInput(attrs={'placeholder':'Password', 'class':'form-control', 'type':'password'})
}
fields = {'first_name', 'last_name', 'email', 'username', 'password'}
def clean(self):
cleaned_data = super(SignUpForm, self).clean()
password = cleaned_data.get('password')
password2 = cleaned_data.get('password2')
if password != password2:
raise forms.ValidationError('Passwords do not match!')
And this is my view:
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
form.save()
user = authenticate(username=username, password=password)
login(request, user)
messages.add_message(request, messages.SUCCESS, 'Account created successfully!')
return HttpResponseRedirect('/')
else:
messages.add_message(request, messages.ERROR, "There's an error in the form! Please fill it again.")
return render(request, 'form/register.html', {'form': form})
else:
form = SignUpForm()
return render(request, 'form/register.html', {'form': form})
And this is my template:
<div class="login-box-body">
{% block login_form %}
<form method="POST">
{% csrf_token %}
{% if form.errors %}
{% for error in field.errors %}
<p class="login-box-msg" style="color: red;">{{ error }}</p>
{% endfor %}
{% endif %}
<div class="form-group has-feedback">
{{form.first_name}}
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
{{form.last_name}}
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
{{form.email}}
<span class="glyphicon glyphicon-envelope form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
{{form.username}}
<span class="glyphicon glyphicon-user form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
{{form.password}}
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="form-group has-feedback">
{{form.password2}}
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
</div>
<div class="row">
<div class="col-xs-8">
<button type="button" class="btn btn-default" onclick="window.location.href='{% url 'manager:login' %}'">Voltar</button>
</div>
<div class="col-xs-4">
<button type="submit" class="btn btn-primary btn-block btn-flat">Criar Conta</button>
</div>
</div>
</form>
{% endblock login_form %}
What am I doing wrong?
Okay, I managed to work it out, at least as a temporary solution! Daniel was right, there was a typo in my template, but it was showing "_ all _" as the error message, not sure why.
Since the password fields were the only ones I was using raise forms.ValidationError function, then the error message was only to be shown in case the passwords wasn't matching.
So I just wrote the error message I wanted directly in my template! Like this:
<form method="POST">
{% csrf_token %}
{% if form.errors %}
<p class="login-box-msg" style="color: red; font-weight: bold;">Passwords do not match!</p>
{% endif %}
It doesn't work the way I wanted, but it does the job!
Related
Good day,
I am making a Django application,
I want to call my data that the user signs up with and to display the information they submitted as:
Name
Email
Then I want to be able to change that data and then I want to save it, and reload back into the dashboard, but when I am updating my 'update_profile.html' the info is not updating, I can; add form data and change it
What am I doing wrong?
My code below:
views.py
from django.shortcuts import render, redirect, HttpResponse
from django.contrib import messages, auth
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from contacts.models import Contact
def register(request):
if request.method == 'POST':
# Get form values
first_name = request.POST['first_name']
last_name = request.POST['last_name']
username = request.POST['username']
email = request.POST['email']
password = request.POST['password']
password2 = request.POST['password2']
# Check if passwords match
if password == password2:
# Check username
if User.objects.filter(username=username).exists():
messages.error(request, 'That username is taken')
return redirect('register')
else:
if User.objects.filter(email=email).exists():
messages.error(request, 'That email is being used')
return redirect('register')
else:
# Looks good
user = User.objects.create_user(
username=username, password=password, email=email, first_name=first_name, last_name=last_name) # noqa
# Login after register
auth.login(request, user)
messages.success(request, 'You are now logged in')
return redirect('index')
# user.save()
# messages.success(
# request, 'You are now registered and can log in')
# return redirect('login')
else:
messages.error(request, 'Passwords do not match')
return redirect('register')
else:
return render(request, 'accounts/register.html')
def login(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = auth.authenticate(username=username, password=password)
if user is not None:
auth.login(request, user)
messages.success(request, 'You are now logged in')
return redirect('dashboard')
else:
messages.error(request, 'Invalid credentials')
return redirect('login')
else:
return render(request, 'accounts/login.html')
def logout(request):
if request.method == 'POST':
auth.logout(request)
messages.success(request, 'You are now logged out')
return redirect('index')
#login_required(login_url='login')
def dashboard(request):
user_contacts = Contact.objects.order_by(
'-contact_date').filter(user_id=request.user.id)
context = {
'contacts': user_contacts
}
return render(request, 'accounts/dashboard.html', context)
#login_required(login_url='login')
def edit_profile(request, pk):
user = User.objects.get(id=pk)
if request.method == 'POST':
...
user.name = request.GET['name']
user.email_address = request.GET['email_address']
user.save()
return redirect('dashboard')
context = {
'user': user
}
return render(request, 'accounts/dashboard.html', context)
#login_required(login_url='login')
def delete_profile(request, pk):
user = User.objects.get(id=pk)
if request.method == 'POST':
...
user.name = request.GET['name']
user.email_address = request.GET['email_address']
user.delete()
return redirect('index')
context = {
'user': user
}
return render(request, 'index.html', context)
Then my urls
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('register', views.register, name='register'),
path('login', views.login, name='login'),
path('logout', views.logout, name='logout'),
path('dashboard', views.dashboard, name='dashboard'),
path('edit_profile/<int:pk>/', views.edit_profile, name='edit_profile'),
]
Lastly My edit_profile.html
{% extends 'base.html' %}
{% block title %} | Edit Profile {% endblock %}
{% block content %}
<section id="showcase-inner" class="py-5 text-white">
<div class="container">
<div class="row text-center">
<div class="col-md-12">
<h1 class="display-4">User Dashboard</h1>
<p class="lead">Manage your BT Real Estate account</p>
</div>
</div>
</div>
</section>
<!-- Breadcrumb -->
<section id="bc" class="mt-3">
<div class="container">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="{% url 'index' %}">
<i class="fas fa-home"></i> Home</a>
</li>
<li class="breadcrumb-item active"> Dashboard</li>
</ol>
</nav>
</div>
</section>
{% comment %} Alerts {% endcomment %}
{% include 'partials/__alerts.html' %}
<section id="dashboard" class="py-4">
<div class="container">
<div class="row">
<div class="col-md-12">
<h2>Welcome {{ user.first_name }}
<a class="btn btn-info" href="{% url 'dashboard' %}">
Save Profile
</a>
<a class="btn btn-da nger" href="{% url 'dashboard' %}">
Del;ete Profile
</a>
</h2>
<h3>Account Details: </h3>
<form action="{% url 'contact' %}" method="POST">
{% csrf_token %}
{% if user.is_authenticated %}
<input type="hidden" name="user_id" value="{{ user.id }}">
{% else %}
<input type="hidden" name="user_id" value="0">
{% endif %}
<input type="hidden" name="realtor_email" value="{{ listing.realtor.email }}">
<input type="hidden" name="listing_id" value="{{ listing.id }}">
<div class="form-group">
<label for="property_name" class="col-form-label">Property:</label>
<input type="text" name="listing" class="form-control" value="{{ listing.title }}" >
</div>
<div class="form-group">
<label for="name" class="col-form-label">Name:</label>
<input type="text" name="name" class="form-control" {% if user.is_authenticated %} value="{{ user.first_name }} {{ user.last_name }}" {% endif %} required>
</div>
<div class="form-group">
<label for="email" class="col-form-label">Email:</label>
<input type="email" name="email" class="form-control" {% if user.is_authenticated %} value="{{ user.email }}" {% endif %} required>
</div>
<div class="form-group">
<label for="phone" class="col-form-label">Phone:</label>
<input type="phone" name="phone" class="form-control" {% if user.is_authenticated %} value="{{ user.phone }}" {% endif %} >
</div>
<input type="submit" value="Send" class="btn btn-block btn-secondary">
</form>
</div>
</div>
</div>
</section>
{% endblock %}
PLEASE HELP!
I have a contact form in Django, and I use crispy in my template, but in both the Class base view and Function base view, my submit button is not working, and I have no errors.
here is my fbv code. I also tried it with cbv
my template is using jquery,bootstrap,moment.js
here is my code:
models.py
class ContactUs(models.Model):
fullname = models.CharField(max_length=150, verbose_name="Full Name")
email = models.EmailField(max_length=150, verbose_name="Email")
message = models.TextField(verbose_name="Message")
is_read = models.BooleanField(default=False)
class Meta:
verbose_name = "contact us"
verbose_name_plural = "Messages"
forms.py:
class CreateContactForm(forms.Form):
fullname = forms.CharField(widget=forms.TextInput(attrs={"placeholder": "Full Name"}),
validators=[
validators.MaxLengthValidator(150,
"Your name should be less than 150 character")
],
)
email = forms.EmailField(widget=forms.EmailInput(attrs={"placeholder": "Email address"}),
validators=[
validators.MaxLengthValidator(150,
"Your email should be less than 150 character")
],
)
message = forms.CharField(widget=forms.Textarea(attrs={"placeholder": "Your Message"}))
views.py:
def contact_page(request):
contact_form = CreateContactForm(request.POST or None)
if contact_form.is_valid():
fullname = contact_form.cleaned_data.get('fullname')
email = contact_form.cleaned_data.get('email')
message = contact_form.cleaned_data.get('message')
ContactUs.objects.create(fullname=fullname, email=email, message=message, is_read=False)
# todo : show user a success message
contact_form = CreateContactForm(request.POST or None)
context = {"contact_form": contact_form}
return render(request, 'contact_page.html', context)
Template:
<form id="contact-form" class="contact-form" data-toggle="validator" novalidate="true" method="post" action="">
{% csrf_token %}
<div class="row">
<div class="form-group col-12 col-md-6">
{{ contact_form.fullname|as_crispy_field }} {% for error in contact_form.fullname.errors %}
<div class="help-block with-errors">{{ error }}</div>
{% endfor %}
</div>
<div class="form-group col-12 col-md-6">
{{ contact_form.email|as_crispy_field }} {% for error in contact_form.email.errors %}
<div class="help-block with-errors">{{ error }}</div>
{% endfor %}
</div>
<div class="form-group col-12 col-md-12">
{{ contact_form.message|as_crispy_field }} {% for error in contact_form.message.errors %}
<div class="help-block with-errors">{{ error }}</div>
{% endfor %}
</div>
</div>
<div class="row">
<div class="col-12 col-md-6 order-2 order-md-1 text-center text-md-left">
<div id="validator-contact" class="hidden"></div>
</div>
<div class="col-12 col-md-6 order-1 order-md-2 text-right">
<button type="submit" name="submit" class="btn"><i class="font-icon icon-send"></i> Send Message</button>
</div>
</div>
</form>
Try adding "save" to the submit button class.
Also your contact_page view does nothing after saving the contact data to the db. If you'll do a pop-up confirmation in JS you don't need to instantiate contact_form the second time. Or if you want to redirect the user:
def contact_page(request):
contact_form = CreateContactForm(request.POST or None)
if contact_form.is_valid():
fullname = contact_form.cleaned_data.get('fullname')
email = contact_form.cleaned_data.get('email')
message = contact_form.cleaned_data.get('message')
ContactUs.objects.create(
fullname=fullname,
email=email,
message=message,
is_read=False
)
return redirect('some-view')
context = {"contact_form": contact_form}
return render(request, 'contact_page.html', context)
Hey guys I am using Sanic with WTForms and Sanic-WTF. I have this code for my SignUpForm:
class SignUpForm(SanicForm):
email = EmailField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired(),
Length(min=3, max=25), EqualTo('confirm_password', message='Passwords must match.')])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired()])
I also have this as my validation for my validation in a Class Based View.
async def post(self, request):
form = SignUpForm(request)
email = form.email.data
print(email)
email_exists = await unique_db(email)
print(form.errors)
print ('Form validated: {}, Email Exists: {}'.format(form.validate_on_submit(), email_exists))
if form.validate_on_submit() and email_exists == False:
print('Validated')
await app.db.user_details.update_one({'user':'details'},{'$set': data}, upsert=True)
return json({'success':True})
return template('signup.html', form=form)
I have no idea what is going on. I have also tried doing form.validate()
My SignUp Form is
<form name="SignupForm" style="padding-top: 50px;" method="post">
{{ form.csrf_token }}
<div class="row justify-content-center">
<div class="col-lg-8 col-md-10 col-sm-12">
<div class="card">
<div class="card-body">
<h3 class="card-title">Sign up</h3>
{{ macros.render_field(form.email, label_visible=true, placeholder='Email', type='email') }}
<small id="passwordHelpBlock" class="form-text text-muted">Your email must be in the form name#example.com</small>
{{ macros.render_field(form.password, label_visible=true, placeholder='Password', type='password') }}
{{ macros.render_field(form.confirm_password, label_visible=true, placeholder='Confirm Password', type='password') }}
<button type="submit" class="btn btn-success" id="login-submit-button">Submit</button>
</div>
<div class="card-footer text-muted text-center">
Already have an account? Log in
</div>
</div>
</div>
</div>
</form>
Ok so their seems to be a bug in SanicForm, because when I changed my SignUpForm class to inherit from Form (the generic WTForm form class) it worked fine.
I am trying to create a registration form using django, when I submit my form the is valid() function fails and I am not sure why. I have my registration and login page all on one html page, although, I have called all the field names different names, eg login_username.
forms.py
class SignUpForm(forms.Form):
username = forms.CharField(label='Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Username'}))
conUsername = forms.CharField(label='Confirm Username', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Username'}))
firstName = forms.CharField(label='First Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Firstname'}))
lastName = forms.CharField(label='Last Name', max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter LastName'}))
email = forms.CharField(label='Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Enter Email','type':'email'}))
conEmail = forms.CharField(label='Confirm Email', max_length=220,widget=forms.TextInput(attrs={'class': 'form-control','placeholder':'Confirm Email','type':'email'}))
password = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Enter Password'}))
conPassword = forms.CharField(label="Confirm Password", max_length=20,widget=forms.TextInput(attrs={'class': 'form-control','type':'password','placeholder':'Confirm Password'}))
views.py
def SignUp(request):
regForm = SignUpForm()
form = LoginForm()
if request.method == 'POST':
if regForm.is_valid():
username = regForm.cleaned_data('username')
print username
confirm_username = regForm.cleaned_data('conUsername')
first_name = regForm.cleaned_data('firstName')
last_name = regForm.cleaned_data('lastName')
email = regForm.cleaned_data('email')
confirm_email = regForm.cleaned_data('conEmail')
password = regForm.cleaned_data('password')
confirm_password = regForm.cleaned_data('conPassword')
#try:
#user = User.objects.get(username=request.POST['username'])
#return render(request, 'index.html',{'error_message':'username must be unique'})
#except User.DoesNotExist:
#user = User.objects.create_user(request.POST['username'], password=request.POST['password'])
#login(request, user)
#return render(request, 'index.html')
else:
return render(request,'index.html',{'username_error':'usernames didnt match','form':form,'regForm':regForm})
else:
return render(request, 'index.html',{'form':form,'regForm':regForm})
index.html
<form class="regForm" method="POST" action="{% url 'signup' %}">
{% csrf_token %}
{{username_error }}
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{regForm.error_message.username}}
{{ regForm.username }}
</div>
</div>
<div class="col-md-2 ">
<div class="form-group">
{{error_message.conUsername}}
{{ regForm.conUsername }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.firstName }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.lastName }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.email }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-4 col-md-offset-8">
<div class="form-group">
{{ regForm.conEmail }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-2 col-md-offset-8">
<div class="form-group">
{{ regForm.password }}
</div>
</div>
<div class="col-md-2">
<div class="form-group">
{{ regForm.conPassword }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 col-md-offset-9">
<div class="form-group">
<button type="submit" id="regBtn" class="btn btn-default">Submit</button>
</div>
</div>
</div>
</form>
Right now your form is always empty and therefore invalid. You forgot to add the request POST content to the form.
def SignUp(request):
# ...
if request.method == 'POST':
regForm = SignupForm(request.POST) # form needs content
if regForm.is_valid():
# ...
If you get stuck when calling .is_valid(), you can print(regForm.errors) to see what's up.
You have two main problems. Firstly, you are never passing the POST data to the form, so it can never be valid.
Secondly, for some reason you are ignoring everything that the form could tell you about why it is not valid, and always returning "usernames didn't match". What's more, you're not even doing anything to compare usernames, so that error message will never be accurate.
You should rework your view to follow the pattern as described in the documentation:
def SignUp(request):
if request.method == 'POST':
regForm = SignUpForm(request.POST)
if regForm.is_valid():
...
return redirect(somewhere)
else:
regForm = SignUpForm()
return render(request, 'index.html', {'regForm':regForm})
and in your template make sure you include {{ form.errors }} to show what the validation failures are.
I'm making a webpage where I login and add people to an address book. Once I login and click on the "add address" button, I'm redirected back to the login page with the following url:
http://localhost:8000/xcard/login/?next=/xcard/add_address/
If I login again I can get to account page, address book, and then add_address book page without being caught in the login loop. I can logout and login and add addresses without relogin in twice. But the first time I ever login I have to do it twice. Not sure if it's a problem with the login or the add address code.
Views.py
class LoginView(View):
def get(self, request):
''' if user is authenticated '''
if request.user.is_authenticated():
return render(request, 'xcard/account.html')
else:
return render(request, 'xcard/login.html')
def post(self, request):
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
state = "The email or password is incorrect"
if user is not None:
login(request, user)
return HttpResponseRedirect('/xcard/account/')
else:
return render(request, 'xcard/login.html', {'state':state})
class AddAddressView(View):
def get(self,request):
address_form = AddressForm()
friend_form = FriendForm()
return render(request, 'xcard/add_address.html', {'friend_form':friend_form, 'address_form':address_form})
def post(self,request):
address_form = AddressForm(request.POST)
friend_form = FriendForm(request.POST)
if address_form.is_valid() and friend_form.is_valid():
new_address = address_form.save()
new_friend = friend_form.save(commit=False)
new_friend.address = new_address
new_friend.save()
return HttpResponseRedirect('/xcard/address_book')
else:
return render(request, 'xcard/add_address.html', {'state' : "Failed", 'friend_form':friend_form, 'address_form':address_form})
Templates:
address_book.html
{% include "xcard/header.html" %}
{% block main %}
<div class="container">
<h3 class="text-info"><u>Your Account</u></h3>
Add
Import
</div>
{% endblock %}
Templates:
login.html
{% extends "xcard/base.html" %}
{% block main %}
<div class="container">
<div class="row space">
<p class="text-center lead text-warning">
Login page</p>
<p class="text-center text-info">Trusted worldwide!</p>
</div>
<div class="row">
<div class="span offset4">
<form class="well" action="/xcard/login/" method="post">
{% csrf_token %}
<p class="lead">Sign In</p>
<fieldset class="login_page">
<p class="text-error"><strong>{{ state }}</strong></p>
<label class="control-label" for ="inputIcon">Email</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-user"></i></span>
<input type="text" class="span3" id="ernainputIcon" required name="username" placeholder="Username...."/><br/><br/>
</div>
</div>
<label>Password</label>
<div class="controls">
<div class="input-prepend">
<span class="add-on"><i class="icon-lock"></i></span>
<input type="password" class="span3" id="inputIcon" required name="password" placeholder="Password...."/><br/><br/><br />
</div>
</div>
<button class="btn btn-primary">Sign In</button>
Not a user?
Sign up
</fieldset>
</form>
</div>
</div>
</div>
{% endblock %}
I just found this in my urls.py
url(r'^add_address/$', login_required(AddAddressView.as_view(), login_url='/xcard/login/')),
Maybe this is causing the problem? But why doesn't it register that I'm already logged in?
first do the correction in AddAddressView function. update line
return render(request, 'xcard/add_address.html', {'friend_form':friend_form, 'address_form':address_form})
it will work
This was my solution - logout before you try to authenticate.
This issue happened to me when users were logging in and logging back in with a different username.
import django.contrib.auth as djangoAuth
djangoAuth.logout(request) # logout
user = djangoAuth.authenticate(username=username, password=password) # login