With this setup, the password isn't stored when someone submits the form on the register page. However, the username and email are stored. Everything displays accurately, with 'password1' and 'password2' linking to a "Password" and "Password confirmation" input field in the web page. Using the default UserCreationForm instead works fine. Does anyone know what code I'm missing?
forms.py:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py:
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from mainsite.forms import MyRegistrationForm
...
def register_user(request):
if request.method == 'POST':
form = MyRegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts/register_success')
args = {}
args.update(csrf(request))
args['form'] = MyRegistrationForm()
return render_to_response('directory/register.html', args)
def register_success(request):
return render_to_response('directory/register_success.html')
register.html:
{% extends "directory/base.html" %}
{% block content %}
<h2>Register</h2>
<form action="/accounts/register/" method="post">{% csrf_token %}
{{ form }}
<input type="submit" value="register" />
</form>
{% endblock %}
I am dealing with the exact same code from Mike Hibbert's Django tutorials. This question was also answered here:
django - no password set after successful registration
When you save the form, call super on MyRegistrationForm instead of UserCreationForm:
def save(self, commit=True):
user = super(MyRegistrationForm, self).save(commit=False)
...
Try this:
user.email = self.cleaned_data['email']
user.set_password(self.cleaned_data['password1'])
user.save()
Related
Before extending the user module, I was easily able to register new users and the page would get redirected to the login page. Now on registering new users, the profile is not getting created and the page is also not getting redirected. The new user does get created though and sometimes the error is object does not exist, user profile does not exist, and sometimes the error is forbidden, csrf verification failed. I dont know where I'm going wrong. existing users are able to login and update profiles but new users I'm having a problem with.
Models.py is:
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User,null= True ,on_delete= models.CASCADE)
profile_pic = models.ImageField(null = True, blank= True)
first = models.CharField(max_length=500, null=True)
last = models.CharField(max_length=500, null=True)
email = models.CharField(max_length=500, null=True)
mobile_number = models.IntegerField(null=True)
location = models.CharField(max_length= 500, null= True)
postal = models.IntegerField(null=True)
def __str__(self):
return self.first
My forms.py is:
from django.forms import ModelForm, fields
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
from .models import *
class CreateUserForm(UserCreationForm):
email = forms.EmailField()
password2 = None
class Meta:
model = User
fields = ['username','first_name', 'last_name','email', 'password1']
class ProfileForm(ModelForm):
class Meta:
model = Profile
fields = '__all__'
exclude = ['user']
widgets = {
'profile_pic': forms.FileInput()
}
views.py is (I removed the login and logout view cause that was working fine):
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from .forms import CreateUserForm, ProfileForm
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from .models import *
def RegisterPage(request):
if request.user.is_authenticated:
return redirect('Profile')
else:
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
user = form.save()
name = form.cleaned_data.get('first_name')
messages.success(request, 'Account created for ' + name)
Profile.object.create(
user = user,
)
Profile.save()
return HttpResponseRedirect('/Login/')
else:
form = CreateUserForm()
context = {'form':form}
return render(request, 'register.html', context)
#login_required(login_url='Login')
def Profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'profile.html', context)
my register template:
<form class="" action="" method="post">
{% csrf_token %}
<p class="reg-field-title"><strong>Username*</strong></p>
<div class="forms">{{form.username}}</div>
<p class="reg-field-title"><strong>First Name*</strong></p>
<div class="forms">{{form.first_name}}</div>
<p class="reg-field-title"><strong>Last Name*</strong></p>
<div class="forms">{{form.last_name}}</div>
<p class="reg-field-title"><strong>Email-ID*</strong></p>
<div class="forms">{{form.email}}</div>
<p class="reg-field-title"><strong>Password*</strong></p>
<div class="forms">{{form.password1}}</div>
<button type="submit" class="btn btn-dark btn-lg col-lg-10 reg-btn">Register</button>
</form>
My login template:
<p class="login-reg">New to MedsPlain? <a class="log-reg-link" href="/Registration/">Register </a>here</p>
<hr> {% if next %}
<form class="" action='/Login/Profile/' method="post"> {% csrf_token %} {%else%}
<form class="" action="/Login/" method="post">
{% endif %} {% csrf_token %}
<p class="login-field-title"><strong>Username*</strong></p>
<input type="text" name="username" class="form-control col-lg-10 log-inp-field" placeholder="Enter Username" required>
<p class="login-field-title"><strong>Password*</strong></p>
<input type="password" name="password" class="form-control col-lg-10 log-inp-field" placeholder="Enter Password" required> {% for message in messages %}
<p id="messages">{{message}}</p>
{% endfor %}
<button type="submit" class="btn btn-dark btn-lg col-lg-10 log-btn">Log In</button>
</form>
I've tried everything as of now, but i don't understand the mistake. Can someone please guide me through cause at this moment i'm frustrated, on the verge of crying and don't understand what to do.
There are basically two problems here:
there is a view Profile, and thus this will override the reference to the Profile model; and
you do not create a model record with Model.object.create(), but with Model.objects.create().
I would advise that you rename your views in snake_case, and remove the wildcard import, this is often not a good idea:
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from .forms import CreateUserForm, ProfileForm
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from .models import Profile
def register_page(request):
if request.user.is_authenticated:
return redirect('Profile')
else:
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
user = form.save()
Profile.objects.create(
user = user,
)
messages.success(request, 'Account created for {user.first_name}')
return HttpResponseRedirect('/Login/')
else:
form = CreateUserForm()
context = {'form': form }
return render(request, 'register.html', context)
#login_required(login_url='Login')
def profile(request):
profile = request.user.profile
form = ProfileForm(instance=profile)
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES, instance=profile)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'profile.html', context)
You will also need to update the urls.py to work with the renamed views.
Can you please help me
Forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class Registrationform(UserCreationForm):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
mobile = forms.CharField(max_length=12, min_length=10)
Business_name = forms.CharField(max_length=64)
email = forms.EmailField(required=True)
password2 = None
class Meta:
model = User
fields = ['username', 'first_name', 'last_name', 'mobile', 'email', 'password1', 'Business_name']
def save(self, commit=True):
user = super(Registrationform, self).save(commit=False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.mobile = self.cleaned_data['mobile']
user.email = self.cleaned_data['email']
user.Business_name = self.cleaned_data['Business_name']
if commit:
user.save()
return user
views.py
#login_required
def home(request):
return render(request, 'users/home.html', {'user': request.user})
home.html
{% block content %}
<p>
{{ user.Business_name }}
{{ user.first_name}}
{{ user.last_name}}
{{ user.email }}
{{user.username}}
{{ user.mobile }}
</p>
{% end block %}
I don't understand why I am not able to fetch data even though doing the right thing.
Please help me as I am newbie in Django.
Are you trying to access the form or models? if you want to submit form, you need to change your view to
def home(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
pass # does nothing, just trigger the validation
else:
form = ContactForm()
return render(request, 'home.html', {'form': form})
and add form tag to your home.html
<form method="post" novalidate>
{% csrf_token %}
<table border="1">
{{ form }}
</table>
<button type="submit">Submit</button>
</form>
I hope this helps!!
I'm really new to Django and I want to teach myself my making a simple note. But I don't understand how django forms work. I made simple template when I can display the user's notes and now I am trying to make a view when the user can add new notes to account using a simple form.
Here is my views.py file
from django.shortcuts import render, redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from .forms import CreateUserForm, CreateNoteForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .models import *
# Create your views here.
def loginPage(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
else:
messages.info(request, 'Username or pasword is incorrect')
context = {}
return render(request, 'accounts/login.html', context)
def registerPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
user = form.cleaned_data.get('username')
messages.success(request, 'Account was created for '+ user)
return redirect('home')
context = {'form': form}
return render(request, 'accounts/register.html', context)
def logoutUser(request):
logout(request)
return redirect('login')
#login_required(login_url='login')
def home(request):
if request.user.is_authenticated:
username = request.POST.get('username')
context = {'username': username}
return render(request, 'accounts/home.html', context)
def notes(request):
username = None
if request.user.is_authenticated:
username = request.user.username
user_id = request.user.pk
user_notes = Note.objects.filter(user=user_id)
context = {
'user_notes': user_notes,
'username': username,
#'user_id' : user_id,
}
return render(request, 'accounts/notes.html', context)
def createNote(request):
username = request.user.username
user_id = request.user.pk
user_notes = Note.objects.filter(user=user_id)
form = CreateNoteForm()
if request.method == 'POST':
form = CreateNoteForm(request.POST)
if form.is_valid():
form.save()
return redirect('notes')
context = {'user_notes': user_notes, 'form': form}
return render(request, 'accounts/create_note.html', context)
forms.py:
from django.forms import ModelForm
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Note
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class CreateNoteForm(forms.ModelForm):
class Meta:
model = Note
fields = ['user', 'title', 'text']
and create_note.html:
{% extends 'accounts/main.html' %}
{% load static %}
{% block content %}
<br>
<br>
<div class="container">
<div class="card text-white bg-dark mb-3">
<div class="container">
<form action="{% url 'notes' %}" method="POST">
<div class="card-body">
{% csrf_token %}
{{form}}
<input type="Submit" name="Submit">
</div>
</form>
</div>
</div>
</div>
{% endblock %}
The problem is the new note isn't added when I submit the data. And also if anyone have other suggestions for structuring my views or making this app better I am happy to read them and learn new ways of improving my project. Sorry for long post. I am really noob.
I am trying to learn how to use the User class and have made a form, but cant get it to display the email, first_name and last_name fields, I have the following code:
forms.py:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
class Meta:
model = User
fields = (
'username',
'email',
'first_name'
'password1',
'password2'
)
def save(self, commit = True):
user super(UserCreationForm, self).save(commit = False)
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
views.py:
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib.auth.forms import UserCreationForm
def index(request):
return HttpResponse('index page')
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('accounts')
else:
form = UserCreationForm()
return render(request, 'accounts/register.html', {'form': form})
# Create your views here.
register.html:
{% extends 'accounts/base.html' %}
{% block head %}
<title> Sign Up</title>
{% endblock %}
{% block body %}
<h2>Sign up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign up</button>
</form>
{% endblock %}
When I go to /accounts/register a form with username, password and password confirmation fields appear and the form works and saves to the database. But where are the first_name, last_name, email fields inlcuded in the User model?
Use RegistrationForm instead of UserCreationForm in your views
replace
from django.contrib.auth.forms import UserCreationForm
to
from .forms import RegistrationForm
form = RegistrationForm()
I create a registation app, where users can register providing a username, email and a password. What I did is make sure that the email field is unique(as you can see in the code below). But I can't figure out how I can show the error in case the a user enters an email address that is already in use.
View
from django.shortcuts import render
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from forms import RegistrationForm
# Create your views here.
def register_user(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('../../membership/register_success')
else:
return HttpResponseRedirect('../../membership/register_failed')
args = {}
args.update(csrf(request))
args['form'] = RegistrationForm()
return render(request,'registration/registration_form.html', args)
def register_success(request):
return render_to_response('registration/registration_success.html')
def register_failed(request):
return render_to_response('registration/registration_failed.html')
Form
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django.utils.translation import ugettext_lazy as _
# forms.py
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'password1', 'password2')
def clean_email(self):
email = self.cleaned_data.get('email')
username = self.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).count():
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return email
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
registration.html
{% extends "base.html" %}
{% block title %}Registration{% endblock %}
{% block content %}
<h1>Registration</h1>
{% if form.errors %}
<h1>ERRORRRRRR same email again???</h1>
{% endif %}
{% if registered %}
<strong>thank you for registering!</strong>
Return to the homepage.<br />
{% else %}
<strong>register here!</strong><br />
<form method="post" action="/membership/register/">{% csrf_token %}
{{ form }}
<input type="submit" name="submit" value="Register" />
</form>
{% endif %}
{% endblock %}
You're showing the form with {{ form }} on the template. That itself should show all the validation errors by default, but in your case, you're redirecting to some other page if the form is invalid. So you can never show the errors unless you pass the errors with the GET parameters. You could change your view to this to get the errors on the signup page itself -
def register_user(request):
args = {}
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('../../membership/register_success')
else:
form = RegistrationForm()
args['form'] = form
return render(request,'registration/registration_form.html', args)
How this works is, if the request method is POST, the form gets initiated with the POST data, then it's validated with the is_valid() call, so the form object now has the validation error messages if it's invalid. If it's valid, it's saved and redirected. If not valid, it comes to the args['form'] = form part where the form object with the error messages is set to the context and then passed to render.
If the request method is not POST, then a form object with no data is instantiated and passed to render().
Now your template should show all the error messages just below each field if there is any error.
forms.py
from django import forms
class RegistForm(forms.Form):
name = forms.CharField(required=True)
email = forms.EmailField(required=True)
password = forms.CharField(required=True)
views.py
from django.shortcuts import render
from django.views.generic import TemplateView
import forms
class Register(TemplateView):
def get(self, request):
return render(request, 'register.html', {})
def post(self, request):
form = forms.RegistForm(request.POST)
if form.is_valid():
print(1)
else:
print(form.errors)
content = {'form':form};
return render(request, 'register.html', content)
register.html
<form action="{% url 'register' %}" method="post">
{% csrf_token %}
<fieldset>
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="">
{{ form.errors.name }}
<label for="mail">Email:</label>
<input type="text" id="mail" name="email">
{{ form.errors.email }}
<label for="password">Password:</label>
<input type="password" id="password" name="password">
{{ form.errors.password }}
</fieldset>
<button type="submit">Sign Up</button>
<p class="message">Already registered? Login</p>
</form>
** Feel free to copy code and enjoy! **
Why not just do something like this:
...
if User.objects.filter(email=email):
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return email
...
If the user already registered, have it raise a validation error. If you don't want it to do this, you can do something like:
...
email_exists = User.objects.filter(email=email):
if email_exists and email_exists.username != username:
raise forms.ValidationError(_("This email address is already in use. Please supply a different email address."))
return email
...
To display the form errors, you use form.is_valid() to make sure that it passes validation. Django says the following for custom validations:
Note that any errors raised by your Form.clean() override will not be associated with any field in particular. They go into a special “field” (called __all__), which you can access via the non_field_errors() method if you need to. If you want to attach errors to a specific field in the form, you need to call add_error().
Then in your template you can use something like {{ form.non_field_errors }}, etc.
See this section in the Django docs, under Using a form in a view and Customizing the form template:
https://docs.djangoproject.com/en/dev/topics/forms/
Class based views are easier.
from django.views import generic
from .forms import RegistrationForm
class RegistrationView(generic.CreateView):
template_class = 'registration/registration_form.html'
form_class = RegistrationForm
success_url = '/success/url'
def form_valid(self, form):
# add a log after save or whatever
super(RegistrationView, self).form_valid(self, form)
The clean methods are automatic with forms and messages render as such,
class based views make life a lot easier and your code DRYer.
Have resolved this error by the following:
from django.core.exceptions import ValidationError
try:
except ValidationError as e: