Editing users in Django - 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.

Related

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')

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

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.

Validation errors don't show in Django form

When I try to test my form with an email which has already been entered into the database it doesn't give the error message like it should, it redirects back to the homepage.
My views.py file looks like this:
from django.shortcuts import render
from .forms import LotteryForm
from django.http import HttpResponseRedirect
# Create your views here.
def lottery_list(request):
return render(request, 'lottery/lottery.html', {})
def lottery_new(request):
if request.method == 'POST':
form = LotteryForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('lottery_submitted')
else:
return render(request, 'lottery/lottery.html' {'form': LotteryForm()})
else:
form = LotteryForm()
return render(request, 'lottery/lottery.html', {'form': LotteryForm()})
My form is:
from django import forms
from django.db import models
from django.forms import ModelForm
from .models import Lottery
from .models import Lottery_user
from django.core.exceptions import ValidationError
class LotteryForm(forms.ModelForm):
lottery_type = forms.ModelChoiceField(queryset = Lottery.objects.all(), empty_label=None)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
lottery_numbers = forms.CharField(max_length=12, required=True)
email = forms.EmailField(required=True)
telephone = forms.CharField(max_length=18,
error_messages={'invalid':'Enter a valid mobile number',
'required':'Enter a valid mobile number'})
def clean_email(self):
email = self.cleaned_data['email']
if Lottery_user.objects.filter(email=email).exists():
raise ValidationError("Email already exists")
return email
if Lottery_user.objects.filter(email=self.cleaned_data['email']).exists():
raise ValidationError("You've already entered")
return email
class Meta:
model = Lottery_user
fields = ['lottery_numbers', 'lottery_type', 'first_name', 'last_name', 'email', 'telephone',]
Template form:
<form action="{% url 'lottery_new' %}" method="post">
{% csrf_token %}
<div class="fieldWrapper">
<label for="lotterytype">Choose a lottery:</label>
{{ form.lottery_type }}
<p>See <a href=lottery_instructions>instructions and rules</a></p>
</div>
<div class="fieldWrapper">
<label for="lotterynumbers">Lottery Numbers:</label>
{{ form.lottery_numbers }}
</div>
<div class="fieldWrapper">
<label for="firstname">First name:</label>
{{ form.first_name }}
</div>
<div class="fieldWrapper">
<label for="lastname">Last name:</label>
{{ form.last_name }}
</div>
<div class="fieldWrapper">
{{ form.email.errors }}
{{ form.email.non_field_errors }}
<label for="email">Email:</label>
{{ form.email }}
</div>
<div class="fieldWrapper">
<label for="phonenumber">Telephone Number:</label>
{{ form.telephone }}
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
I want a user to not be able to enter twice with the same email, so it should error when the user clicks submit with a used email address.
Also, does anyone know how to get the error messages to show before the user submits rather than afterwards?
You return a newly instantiated form when the form is invalid, when you should instead return the invalid form (with the errors). Try:
def lottery_new(request):
if request.method == 'POST':
form = LotteryForm(request.POST)
if form.is_valid():
....
else:
return render(request, 'lottery/lottery.html' {'form': form})

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 {} \;