I m new in Django m creating a signup form if submit the form the data is stored success fully but I m having a error in redirection or login
view.py
from Blog.forms import SignupForm
from django.contrib.auth import authenticate,login
from django.http import HttpResponseRedirect
def signup_form(request):
form=SignupForm()
if request.method=='POST':
form=SignupForm(request.POST)
if form.is_valid():
user=form.save()
user.refresh_from_db()
# load the profile instance created by the signal
user.save()
raw_password = form.cleaned_data.get('password')
user = authenticate(username=user.username, password=raw_password)
login(request, user)
return HttpResponseRedirect('home/')
return render(request,'blog/signup.html',{'form':form})
redirecting in setting file
setting.py
LOGIN_REDIRECT='home/'
LOGOUT_REDIRECT_URL='/logout'
my form file look like that
forms.py
from django.contrib.auth.models import User
class SignupForm(ModelForm):
class Meta:
model=User
fields=['username','first_name','last_name','email','password']
labels={'username':' Enter User Name','password':' Enter Password','email':'Enter Email','first_name':'Enter First Name','last_name':'Enter Last Name'}
widgets={'password':forms.PasswordInput,'username':forms.TextInput(attrs={'class':'form-control','placeholder':'Enter Your User Name'}),
'password':forms.PasswordInput(attrs={'class':'form-control','placeholder':'Enter Your Password'}),
'email':forms.EmailInput(attrs={'class':'form-control','placeholder':'Enter Your Email'}),
'first_name':forms.TextInput(attrs={'class':'form-control','placeholder':'Enter First Name'}),
'last_name':forms.TextInput(attrs={'class':'form-control','placeholder':'Enter Last Name'})
}
urls.py
path('signup/',views.signup_form,name='signup/'),
'Anonymous User' object has no attribute '_meta'
You already have the user when you save the form, so you don't need to call authenticate since you already provide the login() function so I have removed authenticate and login line:
def signup_form(request):
form=SignupForm()
if request.method=='POST':
form=SignupForm(request.POST)
if form.is_valid():
user=form.save()
user.refresh_from_db()
# load the profile instance created by the signal
user.save()
return HttpResponseRedirect('home/')
else:
return render(request,'blog/signup.html',{'form':form})
Related
views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm, UserUpdateForm, ProfileUpdateForm
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
using RegisterForm for Registration form django automatically
activate user.I want to add signup email confirmation before
activating user.
So it is pretty simple, you can give a commit=False while saving the form
if form.is_valid():
user=form.save(commit=False)
# sets the field to False
user.is_active=False
user.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('login')
you have also said that
I want to add signup email confirmation before activating user.
for this, you cancheck out these links from
2017: https://medium.com/#frfahim/django-registration-with-confirmation-email-bb5da011e4ef
or 2018:Django 2 - How to register a user using email confirmation and CBVs?
On trying to register a new user using the wp_register (this is a different type of user), I get the following error:
AttributeError: 'AnonymousUser' object has no attribute '_meta'
There are various answers on this, but none solved my problem.
The system was working fine until I tried to add different views in for the different users (W and WP) I also added the field 'description' (as a test) to the registration form, and am also attempting to create two different profiles for two different users (WPs and Ws). I have created, as you will see below, a separate registration page for wps (user type2), referenced by profile_wp, register_WP etc as well, and on trying to register a user using this form, I receive the error referenced above.
The various relevant bits of my code are below
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm): #form that inherits from the usercreationform
email = forms.EmailField()
class Meta:
model = User
class Register_WP_Form(UserCreationForm): #form that inherits from the usercreationform
email = forms.EmailField()
description=forms.EmailField()
#choice = forms.ChoiceField(required=True, widget=forms.RadioSelect(
#attrs={'class': 'Radio'}), choices=(('option1','I am a W'),('option2','I am a WP'),))
class Meta:
model = User
#when this form validates it creates a new user
#type the fields to be shown on your form, in that order.
fields = ['username','email','password1','password2','description']
class UserUpdateForm(forms.ModelForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username','email']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model= Profile
fields=['image']
views.py
#USERS (register) view.py
from django.shortcuts import render,redirect
from django.contrib.auth.forms import UserCreationForm
from django.contrib import messages #this allows us flash messages for testing
from django.contrib.auth.decorators import login_required
from .forms import UserRegisterForm
from .forms import UserUpdateForm
from .forms import Register_WP_Form
from .forms import ProfileUpdateForm
from django.contrib.auth.decorators import login_required
# Create your views here.
def register(request):
if request.method =='POST':
#this UserRegisterForm is created in forms.py and inherits from UserCreationForm (the ready made form)
form = UserRegisterForm(request.POST) #create a form that has the data that was in request.POST
if form.is_valid(): #is the form valid (do you have a username like this already, passwords match?
form.save()#this just saves the account, hashes the password and it's all done for you!
username = form.cleaned_data.get('username')
messages.success(request,f'Account created for {username}, you can now login.')
return redirect('socialmedia-moreinfo')
else:
form =UserRegisterForm() #if the form input is invalid, render the empty form again
#above we are creating a blank form and rendering it to the template
return render(request, 'users/register.html',{'form':form})
#different types of messages message . debug, inf success warning and error
def register_wp(request):
if request.method =='POST':
#this UserRegisterForm is created in forms.py and inherits from UserCreationForm (the ready made form)
form = Register_WP_Form(request.POST) #create a form that has the data that was in request.POST
if form.is_valid(): #is the form valid (do you have a username like this already, passwords match?
form.save()#this just saves the account, hashes the password and it's all done for you!
username = form.cleaned_data.get('username')
messages.success(request,f'Account created for {username}, you can now login.')
print("SUCCESS")
return redirect('profile-wp')
else:
form =Register_WP_Form() #if the form input is invalid, render the empty form again
#above we are creating a blank form and rendering it to the template
return render(request, 'users/register-wp.html',{'form':form})
#different types of messages message . debug, inf success warning and error
def register_w(request):
if request.method =='POST':
#this UserRegisterForm is created in forms.py and inherits from UserCreationForm (the ready made form)
form = UserRegisterForm(request.POST) #create a form that has the data that was in request.POST
if form.is_valid(): #is the form valid (do you have a username like this already, passwords match?
form.save()#this just saves the account, hashes the password and it's all done for you!
username = form.cleaned_data.get('username')
messages.success(request,f'Account created for {username}, you can now login.')
return redirect('profile')
else:
form =UserRegisterForm() #if the form input is invalid, render the empty form again
#above we are creating a blank form and rendering it to the template
return render(request, 'users/register-w.html',{'form':form})
#different types of messages message . debug, inf success warning and error
#login_required #this is a decorator (adds functionality to an existing function)
def profile(request):
if request.method =='POST':
u_form =UserUpdateForm(request.POST,instance=request.user)
p_form =ProfileUpdateForm(request.POST, request.FILES,instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request,f'Your account has been updated')
return redirect('profile')
else:
u_form =UserUpdateForm(instance=request.user)
p_form =ProfileUpdateForm(instance=request.user.profile)
context={
'u_form': u_form,
'p_form': p_form
}
return render(request,'users/profile.html',context)
#add a login required dectorator that django provides
#we want a user to be logged in to view this profile view
#see the very top to import decorators
def profile_wp(request):
if request.method =='POST':
u_form =UserUpdateForm(request.POST,instance=request.user)
p_form =ProfileUpdateForm(request.POST, request.FILES,instance=request.user.profile)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
p_form.save()
messages.success(request,f'Your account has been updated')
return redirect('profile-wp')
else:
u_form =UserUpdateForm(instance=request.user)
p_form =ProfileUpdateForm(instance=request.user.profile)
context={
'u_form': u_form,
'p_form': p_form
}
return render(request,'users/profile-wp.html',context)
#add a login required dectorator that django provides
#we want a user to be logged in to view this profile view
#see the very top to import decorators
urls.py
#URLS in main project directory
from django.contrib import admin
from django.contrib.auth import views as auth_views #add this for user views
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
from users import views as user_views
#now create paths for the user views (default django user views) below
urlpatterns = [
path('admin/', admin.site.urls),
path('register/',user_views.register, name='register'),
path('register_wp/',user_views.register_wp, name='register_wp'),
path('register_w/',user_views.register_w, name='register_w'),
#path('socialmedia/',include('socialmedia.urls')),
path('login/',auth_views.LoginView.as_view(template_name='users/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(template_name='users/logout.html'), name='logout'),
path('profile/',user_views.profile, name='profile'),
path('profile-wp/',user_views.profile_wp, name='profile-wp'),
path('',include('socialmedia.urls')),
]
if settings.DEBUG:#if we currently in DEBUG mode, then add the below to URL patterns
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
I'm working on a simple login and logout app in Django.
I wrote two views one for login and another for register.
Register view is working as expected. But login view is causing issues.
I'm using form.is_valid() in login view. That is where the issue is arising. If I print the form in else block, it is saying A user with that username already exists. This is happening even before trying to authenticate the user. Some one help me with this.
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.http.response import HttpResponse
from django.shortcuts import render
from notes.forms import UserForm
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
elif request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user:
login(request, user)
return HttpResponse("Logged in")
else:
return HttpResponse("Wrong creds")
else:
print(form)
return HttpResponse("else of is_valid()")
def register(request):
if request.method == 'GET':
return render(request, 'register.html')
elif request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password = form.cleaned_data['password']
email = form.cleaned_data['email']
existing = User.objects.filter(username=username)
if existing:
return HttpResponse('Username is already taken')
else:
User.objects.create(username=username, password = password, email=email)
return HttpResponse("User created with "+ username +" username")
else:
return HttpResponse("Hi")
forms.py
from django.contrib.auth.models import User
from notes.models import Note
from django import forms
class NoteForm(forms.ModelForm):
class Meta:
model = Note
fields = '__all__'
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['username', 'email', 'password']
The form.is_valid() call will validate the form, this is done through several steps. Depending on the fields of the model, it thus also checks the uniqness of the data.
The User [Django-doc] model has a uniqness constraint on the username, hence the UserForm can only be valid, if the username is not yet taken, or when the form contains a instance that is already stored in the database.
I therefore think that it might be better to create a LoginForm, like Django does with an AuthenticationForm [Django-doc] [GitHub]. For example:
class UserForm(forms.Form):
username = forms.CharField()
password = forms.CharField()
The django usermodel django.contrib.auth.models.User has a field 'last_login' record the time when a user is successfully login.
But I donot see a code such as 'last_login=datetime.now()' in function from django.contrib.auth import login or from django.contrib.auth import authenticate. I also checked the django.contrib.auth.signals.user_logged_in.
where is the code for update the field 'last_login'?
Below is all the related source coede,how is the login process invoke the update_last_login? I don't see any code in login views or Authenticate function suoure code.
def update_last_login(sender, user, **kwargs):
"""
A signal receiver which updates the last_login date for
the user logging in.
"""
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
user_logged_in.connect(update_last_login)
from django.dispatch import Signal
user_logged_in = Signal(providing_args=['request', 'user'])
#sensitive_post_parameters()
#csrf_protect
#never_cache
def login(request, template_name='registration/login.html',
redirect_field_name=REDIRECT_FIELD_NAME,
authentication_form=AuthenticationForm,
current_app=None, extra_context=None):
"""
Displays the login form and handles the login action.
"""
redirect_to = request.REQUEST.get(redirect_field_name, '')
if request.method == "POST":
form = authentication_form(request, data=request.POST)
if form.is_valid():
# Ensure the user-originating redirection url is safe.
if not is_safe_url(url=redirect_to, host=request.get_host()):
redirect_to = resolve_url(settings.LOGIN_REDIRECT_URL)
# Okay, security check complete. Log the user in.
auth_login(request, form.get_user())
return HttpResponseRedirect(redirect_to)
else:
form = authentication_form(request)
current_site = get_current_site(request)
context = {
'form': form,
redirect_field_name: redirect_to,
'site': current_site,
'site_name': current_site.name,
}
if extra_context is not None:
context.update(extra_context)
return TemplateResponse(request, template_name, context,
current_app=current_app)
class ModelBackend(object):
"""
Authenticates against settings.AUTH_USER_MODEL.
"""
def authenticate(self, username=None, password=None, **kwargs):
UserModel = get_user_model()
if username is None:
username = kwargs.get(UserModel.USERNAME_FIELD)
try:
user = UserModel._default_manager.get_by_natural_key(username)
if user.check_password(password):
return user
except UserModel.DoesNotExist:
# Run the default password hasher once to reduce the timing
# difference between an existing and a non-existing user (#20760).
UserModel().set_password(password)
user_logged_in signal is connected to django.contrib.auth.models.update_last_login function, it makes:
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
I think the best way of doing this thing is
request_user, data = requests.get_parameters(request)
user = requests.get_user_by_username(data['username'])
update_last_login(None, user)
You can also get user for request object by doing following.
user = request.user
on djnago 1.11
add this class :
class IsAuthenticated(BasePermission):
"""
Allows access only to authenticated users.
"""
def has_permission(self, request, view):
if request.user and request.user.is_authenticated:
user = request.user
user.last_login = timezone.now()
user.save(update_fields=['last_login'])
return request.user and request.user.is_authenticated
on setting file change :
'DEFAULT_PERMISSION_CLASSES': (
# custom class
'IsAuthenticated',
),
This is what I am currently using for registration:
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. Please login to continue.")
return HttpResponseRedirect("/dashboard/")
else:
form = UserCreationForm()
return render_to_response("accounts/register.html", {
'form': form,
}, context_instance=RequestContext(request))
Is it possible not to require the user to login manually after creating an account, but rather simply to log them in automatically? Thanks.
edit: I had tried the login() function without success. I believe the problem is that AUTHENTICATION_BACKENDS was not set.
Using the authenticate() and login() functions:
from django.contrib.auth import authenticate, login
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
messages.info(request, "Thanks for registering. You are now logged in.")
new_user = authenticate(username=form.cleaned_data['username'],
password=form.cleaned_data['password1'],
)
login(request, new_user)
return HttpResponseRedirect("/dashboard/")
for class based views here was the code that worked for me (originally Django 1.7, updated for 2.1)
from django.contrib.auth import authenticate, login
from django.contrib.auth.forms import UserCreationForm
from django.http import HttpResponseRedirect
from django.views.generic import FormView
class SignUp(FormView):
template_name = 'signup.html'
form_class = UserCreateForm
success_url='/account'
def form_valid(self, form):
#save the new user first
form.save()
#get the username and password
username = self.request.POST['username']
password = self.request.POST['password1']
#authenticate user then login
user = authenticate(username=username, password=password)
login(self.request, user)
return HttpResponseRedirect(self.get_success_url)
The accepted answer doesn't seem to work with Django 4.0 (for me, at least), or alternatively it doesn't work with custom user models that have custom user managers.
This is how I solved the issue (adapted from https://stackoverflow.com/a/31491942 and https://stackoverflow.com/a/68515276):
from django.views.generic import CreateView
from django.urls import reverse_lazy
from django.contrib.auth import authenticate, login
from your.custom.user.models import User
class SignUpView(CreateView):
model = User
fields = ["username", "email", "password"]
success_url = reverse_lazy("success_url_name") # change this with your own URL
def form_valid(self, form):
# create the user object
user = form.save(commit=False)
# set password manually
# as otherwise the User will be saved with unhashed password
user.set_password(form.cleaned_data.get("password"))
# save your User object to the database
user.save()
# get email and password
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
# authenticate your user with unhashed password, because `authenticate` hashes it again
authenticated_user = authenticate(email=email, password=password)
# log in
login(self.request, authenticated_user)
return redirect(self.success_url)
You need to manually set the password, so that the database contains the hashed password. Without that, your unhashed password will be saved to the database, which will prevent you from logging in afterwards, as authentication involves hashing the password and checking that against the database.
using only "login()" in django-4.0.3
from django.contrib.auth import login
def registration(request):
if request.POST:
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
username = form.cleaned_data.get('username')
messages.success(request, f'Account created for {username}')
return redirect('home')
You can subclass Django's UserCreationForm and override it's save method to log them in when commit=True.
forms.py
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login
class CustomUserCreationForm(UserCreationForm):
"""
A ModelForm for creating a User and logging
them in after commiting a save of the form.
"""
def __init__(self, request, *args, **kwargs):
super().__init__(*args, **kwargs)
self.request = request
class Meta(UserCreationForm.Meta):
pass
def save(self, commit=True):
user = super().save(commit=commit)
if commit:
auth_user = authenticate(
username=self.cleaned_data['username'],
password=self.cleaned_data['password1']
)
login(self.request, auth_user)
return user
You just need to make sure you pass in a request object when you instantiate the form. You can do that by overriding the view's get_form_kwargs method.
views.py
def get_form_kwargs(self):
form_kwargs = super().get_form_kwargs()
form_kwargs['request'] = self.request
return form_kwargs
Or, make sure when you instantiate a form_class you do CustomUserCreationForm(data=request.POST, request=self.request).
The Django auth.login function makes it easy to log in a user, given a request and User instance.
Note: remember to add the necessary imports for the following examples.
from django.contrib.auth import login
from django.shortcuts import render, redirect
In a function-based view, the following should work.
if form.is_valid():
user = form.save()
login(request, user)
return redirect("desired-url")
For a class-based view (such as CreateView or FormView), you can override the form_valid method:
def form_valid(self, form):
"""If the form is valid, save the associated model and log the user in."""
user = form.save()
login(self.request, user)
return redirect(self.success_url)