How to add user-registration form to my django app? - django

I have been able to create a form where the user can input their username and password following this tutorial.
I want to be able to create a user account by: pressing a button which will transfer the user to another page where they will fill out a form and the details are saved onto a database. I also want to make sure that no username is repeated. However, I don't know how to code it. I am very new to django hence why I am struggling.
I am using windows and atom code editor if that makes a difference. Please can someone help me code it.

You can follow this youtube tutorial, it really helped me and if you follow it completely you'll by more familiar with the django configuration.
Update
Also, you can follow this steps:
1.- Create a forms.py file inside your app directory with the following code
# we import the django default user model
from django.contrib.auth.models import User
# also, import the forms to create em
from django import forms
# define a class for your form, it can be anithing you want
class UserForm(forms.ModelForm):
# password = forms.CharField(widget=forms.PasswordInput)
# this Meta class is the way we send information for our form
class Meta:
# define the model
model = User
# define the fields you need (note that username and password are required)
fields = [
'password',
'username',
'first_name',
'last_name',
'is_staff',
'email',
]
# then, in widgets you can define the input type of the field and give
# attributes to each one
widgets = {
'password': forms.PasswordInput(attrs={'class': 'form-control', 'name': 'username'}),
'username': forms.TextInput(attrs={'class': 'form-control', 'name': 'username', 'placeholder': 'username'}),
'first_name': forms.TextInput(attrs={'class': 'form-control', 'name': 'first_name', 'placeholder': 'First Name'}),
'last_name': forms.TextInput(attrs={'class': 'form-control', 'name': 'last_name', 'placeholder': 'Last Name'}),
'is_staff': forms.CheckboxInput(attrs={'class': 'form-control', 'name': 'is_staff'}),
'email': forms.TextInput(attrs={'class': 'form-control', 'name': 'email', 'placeholder': 'email'}),
}
2.- Then you have to create the view.py file inside the app directory (if not created)
# import the View form django and the UserForm we created on step 1
from django.views.generic import View
from .forms import UserForm
# And some other things we need
from django.core.urlresolvers import reverse_lazy
from django.http import HttpResponseRedirect
from django.contrib.auth.models import User # we also need this one
from django.shortcuts import render
from django.contrib import messages
from django.views import generic
# create the class view, named as you need
class UserFormView(View):
# define the form to use, in this case the form we created
form_class = UserForm
# define the template_name, your main html file wher your are goin to use the form
template_name = 'usersControll/add.html'
# and the reverse_lazy is helpfull when the user succesfully added a new user
# replace 'users-add' with the name of your rute
success_url = reverse_lazy('users-add')
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form, request)
def form_valid(self, form):
# when the info the user gave us is valid, stop the commit
# so we can give some nice format to this info
user = form.save(commit=False)
# the "form.cleaned_data" help us to give a standar format to the info
username = form.cleaned_data['username']
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
password = 'tempPass'
user.set_password(password)
# aaand we save it to the database
user.save()
# in my case a send a succesfull massage to the user indicating that
# went fine
messages.add_message(self.request, messages.SUCCESS, "El usuario <b>form.cleaned_data['first_name']</b> fue registrado exitosamente.")
return super(UserFormView, self).form_valid(form)
def form_invalid(self, form, request):
return render(request, self.template_name, {'form': form})
3.- Add the route in your urls.py file
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^add/', views.UserFormView.as_view(), name='users-add'),
# dont forget to add the .as_view() because our view is a class and not a function
]
4.- finally just add the form in your html file
<form action="" method="post">
<div class="panel panel-default">
<div class="panel-body">
{% csrf_token %}
{% if messages %}
{% for msg in messages %}
<div class="alert alert-{{msg.level_tag}} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">x</button>
{% autoescape off %}
{{ msg.message }}
{% endautoescape %}
</div>
{% endfor %}
{% endif %}
{% if form.errors %}
<div class="alert alert-danger alert-dismissible">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">x</button>
<i class="fa fa-bug"></i> Oops, algo salió mal.
</div>
{% endif %}
<div class="col-lg-6">
<div class="form-group {% if form.first_name.errors %} has-error {% endif %}">
<label class="control-label" for="first_name">Nombre</label>
{{ form.first_name }}
<p class="help-block">{{ form.first_name.errors.as_text }}</p>
</div>
<div class="form-group {% if form.last_name.errors %} has-error {% endif %}">
<label class="control-label" for="last_name">Apellido</label>
{{ form.last_name }}
<p class="help-block">{{ form.last_name.errors.as_text }}</p>
</div>
<div class="form-group {% if form.username.errors %} has-error {% endif %}">
<label class="control-label" for="username">Nombre de Usuario</label>
{{ form.username }}
<p class="help-block">{{ form.username.errors.as_text }}</p>
</div>
<div class="form-group {% if form.email.errors %} has-error {% endif %}">
<label class="control-label" for="email">Correo Electronico</label>
{{ form.email }}
<p class="help-block">{{ form.email.errors.as_text }}</p>
</div>
<div class="form-group {% if form.is_staff.errors %} has-error {% endif %}">
<label class="control-label" for="is_staff">Administrador</label>
{{ form.is_staff }}
<p class="help-block">{{ form.is_staff.errors.as_text }}</p>
</div>
</div>
</div> <!-- panel-body -->
<div class="panel-footer">
<input class="btn btn-success btn-sm" type="submit" value="Registrar">
</div> <!-- panel-footer -->
</div> <!-- panel -->
</form>
Hope this is usefull for you.

Related

Django: To check if old password entered by the user is valid or not

I am able to check the new_password1 and new_password2, but I am unable to check whether the old password entered by the user is right or not. As it is not giving me the ValidationError on old password on the django template. Please suggest me the condition that can be used on forms.py
This is forms.py
class ChangePasswordForm(forms.Form):
old_password = forms.CharField(
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': 'Password'}))
new_password1 = forms.CharField(
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': 'Password'}))
new_password2 = forms.CharField(
widget=forms.PasswordInput(
attrs={'class': 'form-control', 'placeholder': 'Password'}))
def set_user(self, user):
self.user = user
def clean(self):
old_password = self.cleaned_data.get('old_password')
valpwd = self.cleaned_data.get('new_password1')
valrpwd = self.cleaned_data.get('new_password2')
if not old_password:
raise forms.ValidationError({
'old_password':"You must enter your old password."})
elif valpwd != valrpwd:
raise forms.ValidationError({
'new_password1': 'Password Not Matched'})
return self.cleaned_data
This is views.py
class PasswordsChangeView(FormView):
template_name = 'dashboard/password/password_change.html'
form_class = ChangePasswordForm
success_url = reverse_lazy('dashboard:admin_login')
def get_form(self):
form = super().get_form()
form.set_user(self.request.user)
return form
This is change_password.html
<form method="POST">
{% csrf_token %}
<div class="input-group mb-3">
<h6>Old Password</h6>{{form.old_password}}
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-lock"></span>
</div>
</div>
</div>
<span style="color:red">{{ form.old_password.errors }}</span>
<div class="input-group mb-3">
<h6>New Password</h6> {{form.new_password1}}
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-lock"></span>
</div>
</div>
</div>
<div class="input-group mb-3">
<h6>Re-Type Password</h6>
{{form.new_password2}}
<div class="input-group-append">
<div class="input-group-text">
<span class="fas fa-lock"></span>
</div>
</div>
<span style="color:red">{{ form.new_password1.errors }}</span>
</div>
{% comment %} {{ form.as_p }} {% endcomment %}
<button class="btn btn-secondary" type="submit">Change Password</button>
</form>
There is a build_in check_password method in django. You have to use check_password() method with user instance.
It will be like:
if user.check_password(old_password):
# you logic
else:
# old password is not correct
Hope it will work for you.
You can use check_password(). For example, in your views.py:
from django.contrib.auth.hashers import check_password
from django.contrib.auth import update_session_auth_hash
from django.contrib import messages
if check_password(current_password, request.user.password):
new_password = form.cleaned_data['...']
confirm_password = form.cleaned_data['...']
if new_password == confirm_password:
# write your code here
update_session_auth_hash(request, request.user) # <-- This code will keep session when user change password
else:
messages.add_message(request, messages.ERROR, 'Password confirmation doesnt match password.')
else:
messages.add_message(request, messages.ERROR, 'Invalid password.')
django.contrib.auth.hashers module also has a make_password() help you hash your password.

Get error message from imported/external validator to print django

I am trying to build a simple user registration page. I want it to include a captcha for validation purposes. I am using django-simple-captcha for this purpose. (If there's a better library, tell me...)
So far everything is working great, EXCEPT that when a captcha is incorrect the user is not notified--they are simply returned to the registration screen. How can I get a specific ValidationError message printed when the captcha is invalid? (I'm also using django-crispy-forms, if that makes any difference)
template:
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Registration</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
<div class="border-top pt-3">
<small class="text-muted">Already Have An Account?<a class="ml-2" href="{% url 'login' %}">Log in</a></small>
</div>
</div>
{% endblock content %}
form model:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2'] # including 'captcha here didn't seem to make a difference
and the view:
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
*do unrelated things*
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'register-template-url', {'form': form})
from simplecaptcha.fields import CaptchaField----
if you are importing CaptchaField like this it will work. If it not works just simply do 1 change as shown below
from simplecaptcha import captcha,captchaform
#captchaform('captcha')
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(validators=[validate_email])
captcha = CaptchaField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2','captcha']

Django Error Styling with Twitter Bootstrap

I am trying to style errors using twitter bootstrap in my Django project. Right now, I have a simple form that asks for a person's email address, has them press a button, and then submits it to the database. It also has validation checking to see if the email is unique in the database. If it is not unique, it raises an error saying "This email is already registered". However, when the error is raised, for a duplicate email, it brings an ugly bullet point list next to the input field with the text This email is already registered. I'm trying to style it to where it has a little dialog show under the input text with a yellow i icon like it does when the input does not include an # sign, i.e. it isn't an email. The ugly bullet point also appears when a valid domain isn't included in the email, e.g. there isn't a .com appended.
I think the problem lies with the way my form html is set up, or how the view handles the form's errors. Maybe, because the form field is an EmailField, the is_valid indicator doesn't validate and therefore shows the twitter bootstrap alert.
How do I get it to show the alert every time? Below is my code:
form part of the index.html
<form class="form-inline" method="post">
<div class="input-group input-group-newsletter">
<div class="form-group">
{% csrf_token %}
{{ form }}
</div>
<div class="form-group">
<div class="input-group-append">
<button class="btn btn-secondary" type="submit">Button Text</button>
</div>
</div>
</div>
</form>
views.py
from django.shortcuts import render, HttpResponse
from django.views.generic import TemplateView
from appname.forms import AppForm
class AppView(TemplateView):
template_name = 'apps/index.html'
def get(self, request):
form = AppForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = AppForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
form.save()
form = AppForm()
args = {'form': form, 'email': email, 'signedup': True}
else:
args = {'form': form, 'signedup': False}
return render(request, self.template_name, args)
forms.py
from django import forms
from .models import AppModel
class AppForm(forms.ModelForm):
email = forms.EmailField(required=True,
label='',
widget=forms.EmailInput(attrs={'class': 'form-control',
'placeholder': 'Enter email...',
'name': 'email',
'aria-label': 'Enter email...',
'aria-describedby': 'basic-addon'}))
class Meta:
model = AppModel
fields = ('email',)
def clean_email(self, *args, **kwargs):
email = self.cleaned_data.get("email")
if AppModel.objects.filter(email__iexact=email).exists():
raise forms.ValidationError("This email is already registered.")
return email
You may want to try Django messages framework. This site shows how its done. I have tried it myself and works fine, though I haven't tried putting icons into it.
https://simpleisbetterthancomplex.com/tips/2016/09/06/django-tip-14-messages-framework.html
Update based on the comment below:
Here are the snippets in my project
in settings.py
from django.contrib.messages import constants as messages
...
MESSAGE_TAGS = {
messages.DEBUG: 'alert-info',
messages.INFO: 'alert-info',
messages.SUCCESS: 'alert-success',
messages.WARNING: 'alert-warning',
messages.ERROR: 'alert-danger',
}
messages.html template which can be included in any template where you want to have notifications
{% if messages %}
{% for message in messages %}
<div class="alert {{ message.tags }} alert-dismissible " role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{ message }}
</div>
{% endfor %}
{% endif %}
log-in.html template
<body>
{% include 'trip_monitor/messages.html' %}
<div class="login-form">
<form method="post">
{% csrf_token %}
<h2 class="text-center">Materials Management</h2>
<p align="center">Please <strong>log in</strong> to continue.</p>
<div class="form-group">
<input name="username" type="text" class="form-control" placeholder="Username" required="required" autofocus>
</div>
<div class="form-group">
<input name="password" type="password" class="form-control" placeholder="Password" required="required" id="password">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary btn-block">Log in</button>
</div>
</form>
</div>
</body>
views.py
from django.contrib import messages
def login(request):
if request.method == 'POST':
_username = request.POST['username']
_password = request.POST['password']
user = authenticate(request, username=_username, password=_password)
if user is not None:
auth_login(request, user)
return redirect('/trip/')
else:
messages.error(request, 'Username or Password is incorrect!') # this will be shown as pop-up message
return render(request, 'trip_monitor/login.html')
elif request.method == 'GET':
if request.user.is_authenticated:
return redirect('/trip/')
else:
return render(request, 'trip_monitor/login.html')

Editing users in Django

I was trying to to edit a user using the form that i used to create the user,
I have no idea why i'm getting an error A user with that username already exists.
Here is my view:
def registration_edit(request):
""" Registration Step2:
The user should be authenticated to reach this step.
Authentication is provided by first step or user login.
"""
if request.user.is_authenticated():
if request.POST:
form = RegistrationForm(request.POST or None, instance=request.user)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('reg_step_2'))
else:
form = RegistrationForm(instance=request.user)
page = 'account'
title = 'Editing User Registration'
context = {'title': title, 'form': form, 'page': page}
template = 'customer/registration.djhtml'
return render_to_response(template, context, context_instance=RequestContext(request))
else:
messages.info(request, '<strong>Note</strong>: You must logged in to edit your account.')
return HttpResponseRedirect('/')
forms.py I did this form because I want to include firstname and lastname field be included on the registration.
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
class Meta:
model = User
exclude = ('is_staff', 'is_active', 'is_superuser', 'last_login', 'date_joined', 'groups', 'user_permissions', 'password')
and here is my template
<form class="form-horizontal" action='.' method="POST">
{% csrf_token %}
<fieldset>
<div id="legend">
<legend class="">
{{ title|title }}
</legend>
</div>
{% for f in form %}
<div class="control-group">
<label class="control-label" for="username">{{ f.label }}</label>
<div class="controls">
{{ f }} <i style="color: orange">{{ f.errors|striptags }}</i>
</div>
</div>
{% endfor %}
<div class="controls">
<button class="btn btn-success">
Continue
</button>
</div>
</fieldset>
</form>
Anyone tell me where i was messing around here?
Any help would be much appreciated.
Your from inherits from UserCreationForm which cleans the username field.
In this case see UserChangeForm instead.

Issues with validation

I have some issues with validation.When i am submitting the form, the form.is_valid():
always returns false.
After modifying the form i.e. after removing all validations from the form, it still return the false(my form is not submitted)
the code of html
{% extends "base.html" %}
{% block extrahead %}
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js" type="text/javascript"></script>
<script>
$(function() {
$( "#id_birthday" ).datepicker();
});
</script>
{% endblock %}
{% block content %}
<form action="" method="post">
{% csrf_token %}
<div class="register_div">
<p><label for="username">Username:</label></p>
<p>{{ form.username }}</p>
</div>
<div class="register_div">
<p><label for="email">Email:</label></p>
<p>{{ form.email }}</p>
</div>
<div class="register_div">
<p><label for="password">Password:</label></p>
<p>{{ form.password }}</p>
</div>
<div class="register_div">
<p><label for="password1">Verify Password:</label></p>
<p>{{ form.password1 }}</p>
</div>
<div class="register_div">
<p><label for="birthday">Birthday:</label></p>
<p>{{ form.birthday }}</p>
</div>
<div class="register_div">
<p><label for="name">Name:</label></p>
<p>{{ form.username }}</p>
</div>
<p><input type="submit" value="submit" alt="register"/></p>
</form>
{% endblock %}
the code of forms.py
from django import forms
from django.contrib.auth.models import User
from django.forms import ModelForm
from drinker.models import Drinker
class RegistrationForm(ModelForm):
username = forms.CharField(label=(u'User Name'))
email = forms.EmailField(label=(u'Email Address'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
password1 = forms.CharField(label=(u'Verify Password'), widget=forms.PasswordInput(render_value=False))
class Meta:
model=Drinker
exclude=('user',)
def clean_username(self):
username=self.cleaned_data['username']
try:
User.objects.get(username=username)
except User.DoesNotExist:
return username
raise forms.ValidationError("The Username is already taken, please try another.")
def clean_password(self):
password=self.cleaned_data['password']
password1=self.cleaned_data['password1']
if password1 != password:
raise forms.ValidationError("The Password did not match, please try again.")
return password
class LoginForm(forms.Form):
username = forms.CharField(label=(u'User Name'))
password = forms.CharField(label=(u'Password'), widget=forms.PasswordInput(render_value=False))
and the code of views.py
def DrinkerRegistration(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/profile/')
if request.method == 'POST':
form = RegistrationForm(request.POST)
#return render_to_response('register')
if form.is_valid():
user=User.objects.create_user(username=form.cleaned_data['username'], email=form.cleaned_data['email'], password = form.cleaned_data['password'])
user.save()
# drinker=user.get_profile()
# drinker.name=form.cleaned_data['name']
# drinker.birthday=form.cleaned_data['birthday']
# drinker.save()
drinker=Drinker(user=user,name=form.cleaned_data['name'],birthday=form.cleaned_data['birthday'])
drinker.save()
return HttpResponseRedirect('/profile/')
else:
return render_to_response('register.html',{'form':form} , context_instance=RequestContext(request))
else:
''' user is not submitting the form, show them a blank registration form '''
form = RegistrationForm()
context={'form':form}
return render_to_response('register.html',context , context_instance=RequestContext(request))
the model code
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class Drinker(models.Model):
user =models.OneToOneField(User)
birthday =models.DateField()
name =models.CharField(max_length=100)
def __unicode__(self):
return self.name
#create our user object to attach to our drinker object
def create_drinker_user_callback(sender, instance, **kwargs):
drinker, new=Drinker.objects.get_or_create(user=instance)
post_save.connect(create_drinker_user_callback, User)
I can see two possible reasons:
Your template contains two usages of username: once at the top and once at the bottom. The form might fail because this does not fit into a single CharField.
It's hard to say without your model class, but maybe it contains fields you haven't explicitly excluded?
If it's not option 1, could you post your Drinker model as well?
Did you checked the errors reporting while validating?
use print form.errors and check your console for error messages
If your code changes aren't reflecting in the run environment, look at removing your *.pyc files. These sometimes can get cached.
For linux OS you can run the following from the root of your project;
find . -iname "*.pyc" -exec rm -f {} \;