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)
Related
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})
I have a following simple view in my views.py for registration on my django site:
def register_user(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
messages.succes(request, ('You have registered'))
return redirect('home')
else:
form = UserCreationForm()
context = {'form': form}
return render(request, 'register.html', context)
That approach would allow anyone to register but I want to allow only selected people to be able to register. I have a simple model for my database
class EmailList(models.Model):
email_addres = models.CharField(max_length=300, blank=True)
def __str__(self):
return self.email_addres
with some e-mail addreses (my site doesn't have usernames, your username is an email addres) and I want to allow registration only for email addresses that are in that database. How would I perform such check?
There is a functionality in Django that limits an access to users that pass a certain test: https://docs.djangoproject.com/en/3.2/topics/auth/default/#limiting-access-to-logged-in-users-that-pass-a-test
You need to create a test function (verifying that the user is in allowed users list), and then use user_passes_test decorator on the view. In case you are using class based views, you need to use a UserPassesTestMixin.
Assuming your code works properly, just grab the contents of the AllowedUsers model and check whether the username is in the queryset.
models.py
class AllowedUsers(models.Model):
allowed_email = models.EmailField(max_length=256)
def __str__(self):
return self.allowed_email
views.py
def register_user(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
object = form.save(commit=False)
allowed_emails = [user.allowed_email for user in AllowedUsers.objects.all()]
if object['username'] in allowed_emails:
form.save()
username = form.cleaned_data['username']
password = form.cleaned_data['password1']
user = authenticate(username=username, password=password)
login(request, user)
messages.success(request, ('You have registered'))
return redirect('home')
else:
return redirect('/login/?next=%s' % request.path)
I should say that if it were me, I'd be doing this while overriding the form_valid method of the default LoginView
Alternative views.py
from django.contrib.auth import views as auth_views
from django.forms import ValidationError
class LoginView(auth_views.LoginView):
def form_valid(self, form):
allowed_emails = [user.allowed_email for user in AllowedUsers.objects.all()]
if form.cleaned_data['username'] in allowed_emails:
return super().form_valid(form)
else:
self.add_error('username', ValidationError("The provided username is not allowed"))
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()
I am trying to achieve two different views: one for registration purpose and one for login purpose.
Now, the registration process works perfectly but the authentication process does not.
Here's the code:
in forms.py the first form called UserForm is used to sign up users, the second form called LoginForm is used to log in users.
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['first_name', 'last_name', 'username', 'email', 'password']
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password']
in views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import Step, Cycle, Program, MotorSetting, GeneralSetting
from django.views import generic
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.core.urlresolvers import reverse_lazy
from django.contrib.auth import authenticate, login
from django.views.generic import View
from .forms import UserForm
from .forms import LoginForm
class UserFormView(View):
form_class = UserForm
template_name = 'programs/registration_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
#storing the data but NOT SAVING them to db yet
user = form.save(commit=False)
#cleaning and normalizing data
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user.set_password(password)
#saving to db
user.save()
#if credentials are correct, this returns a user object
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('programs:index')
return render(request, self.template_name, {'form': form})
class LoginFormView(View):
form_class = LoginForm
template_name = 'programs/login_form.html'
# display blank form
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
#process form data
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
#storing the data but NOT SAVING them to db yet
user = form.save(commit=False)
#if credentials are correct, this returns a user object
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(request, user)
return redirect('programs:index')
return render(request, self.template_name, {'form': form})
in app/urls.py
from django.conf.urls import include, url
from . import views
app_name = 'programs'
urlpatterns = [
#register page
url(r'^register/$', views.UserFormView.as_view(), name='register'),
#login page
url(r'^login/$', views.LoginFormView.as_view(), name='login'),
]
The registration process goes smoothly, the authentication/login does not. When I fill in the form to login and press send, nothing happens apart from the form getting blank again.
Is there any error I'm not seeing in the code?
Many thanks!
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',
),