I have a web page developed in django that uses the django authentication system. To log in to a user, I need their username and password, but I would like to create a login that allows me to enter only by entering the username without the need to use a password, is this possible?
Django View
class LoginView(SuccessURLAllowedHostsMixin, FormView):
"""
Display the login form and handle the login action.
"""
form_class = AuthenticationForm
authentication_form = None
redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'registration/login.html'
redirect_authenticated_user = False
extra_context = None
#method_decorator(sensitive_post_parameters())
#method_decorator(csrf_protect)
#method_decorator(never_cache)
def dispatch(self, request, *args, **kwargs):
if self.redirect_authenticated_user and self.request.user.is_authenticated:
redirect_to = self.get_success_url()
if redirect_to == self.request.path:
raise ValueError(
"Redirection loop for authenticated user detected. Check that "
"your LOGIN_REDIRECT_URL doesn't point to a login page."
)
return HttpResponseRedirect(redirect_to)
return super().dispatch(request, *args, **kwargs)
def get_success_url(self):
url = self.get_redirect_url()
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
def get_redirect_url(self):
"""Return the user-originating redirect URL if it's safe."""
redirect_to = self.request.POST.get(
self.redirect_field_name,
self.request.GET.get(self.redirect_field_name, '')
)
url_is_safe = is_safe_url(
url=redirect_to,
allowed_hosts=self.get_success_url_allowed_hosts(),
require_https=self.request.is_secure(),
)
return redirect_to if url_is_safe else ''
def get_form_class(self):
return self.authentication_form or self.form_class
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['request'] = self.request
return kwargs
def form_valid(self, form):
"""Security check complete. Log the user in."""
auth_login(self.request, form.get_user())
return HttpResponseRedirect(self.get_success_url())
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
current_site = get_current_site(self.request)
context.update({
self.redirect_field_name: self.get_redirect_url(),
'site': current_site,
'site_name': current_site.name,
**(self.extra_context or {})
})
return context
Django Form
class AuthenticationForm(forms.Form):
username = UsernameField(widget=forms.TextInput(attrs={'autofocus': True}))
password = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
)
error_messages = {
'invalid_login': _(
"Please enter a correct %(username)s and password. Note that both "
"fields may be case-sensitive."
),
'inactive': _("This account is inactive."),
}
def __init__(self, request=None, *args, **kwargs):
self.request = request
self.user_cache = None
super().__init__(*args, **kwargs)
# Set the max length and label for the "username" field.
self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
self.fields['username'].max_length = self.username_field.max_length or 254
if self.fields['username'].label is None:
self.fields['username'].label = capfirst(self.username_field.verbose_name)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username is not None and password:
self.user_cache = authenticate(self.request, username=username, password=password)
if self.user_cache is None:
raise self.get_invalid_login_error()
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
if not user.is_active:
raise forms.ValidationError(
self.error_messages['inactive'],
code='inactive',
)
def get_user(self):
return self.user_cache
def get_invalid_login_error(self):
return forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username': self.username_field.verbose_name},
)
Regards.
i don't understand why would you log user in without password but yes ofc you can(however it doesn't make any sense). you need to customize the django authentication system. here is the official docs to the topic
i suggest you to write your own authentication backend like the docs
Related
I am create a application where admin and customer login same browser.
I read many blog not able not fix my problem. As Django use session based login.
I am facing issue while logout my admin then my customer automatic logout. maybe session based functionally
My admin LoginView and Logoutview:
class AdminLoginView(SuccessMessageMixin,LoginView):
authentication_form = LoginForm
template_name = 'login.html'
redirect_field_name = reverse_lazy('admin_panel:dashboard')
redirect_authenticated_user = False
success_message = '%(username)s login Successfully !'
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
# messages.info(self.request, f"{self.request.user.firstname} is already Logged In")
return redirect('/admin/dashboard/')
return super().dispatch(*args, **kwargs)
def get_success_url(self):
url = self.get_redirect_url()
LOGIN_REDIRECT_URL = reverse_lazy('admin_panel:dashboard')
return url or resolve_url(LOGIN_REDIRECT_URL)
class LogoutView(LogoutView):
"""
Log out the user and display the 'You are logged out' message.
"""
next_page = "/admin/login"
def dispatch(self, request, *args, **kwargs):
response = super().dispatch(request, *args, **kwargs)
messages.add_message(request, messages.INFO,'Successfully logged out.')
return response
I have implemented customer based login & logout
def LoginView(request):
form = LoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
remember_me = form.cleaned_data["remember_me"]
user = User.objects.get(email=username)
if user and user.check_password(password):
if user.is_active:
if remember_me == False:
request.session.set_expiry(0)
request.session['user_id'] = user.id
request.session['username'] = user.email
return HttpResponseRedirect('/')
else:
context = {'auth_error': "You're account is disabled"}
return render(request, 'forntend-signin.html', context )
else:
context = {
'auth_error': 'username and password incorrect'
}
return render(request, 'forntend-signin.html', context)
else:
context = {
"form": form
}
return render(request, 'forntend-signin.html', context)
def customer_logout(request):
try:
if request.session['username']:
del request.session['user_id']
del request.session['username']
else:
del request.session['user_id']
except KeyError:
HttpResponseRedirect("/")
return HttpResponseRedirect("/")
Please suggest me how to fix this issue.
If there any documentation available the please share.
I want to register users by using template, i want also, in the moment of registration, set the group(default groups permission provided by Django) of every new user created, I set the group of user in the template but when i look to the group of user in the database i I found it empty.
class ProfileUserManager(BaseUserManager):
def create_user(self, username, password,**extra_fields):
user = self.model(username=username, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, password,**extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username,password,**extra_fields)
class ProfileUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
username = models.CharField(max_length=255,unique=True)
first_name=models.CharField(max_length=255)
last_name= models.CharField(max_length=255)
departement= models.CharField(max_length=255)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
objects = ProfileUserManager()
def __str__(self):
return self.username
forms.py
class FormAddAccount(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = get_user_model()
fields = ('email', 'password1', 'password2', 'is_staff','username','groups','first_name','last_name','departement')
first, you create decoratorsy.py in your app then add the following code in decorators.py
from django.http import HttpResponse
from django.shortcuts import redirect
def unauthenticated_user(view_func):
def wrapper_func(request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('url')
else:
return view_func(request, *args, **kwargs)
return wrapper_func
def allowed_users(allowed_roles=[]):
def decorator(view_func):
def wrapper_func(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group in allowed_roles:
return view_func(request, *args, **kwargs)
else:
return HttpResponse('You are not authorized to view this page')
return wrapper_func
return decorator
def admin_only(view_func):
def wrapper_function(request, *args, **kwargs):
group = None
if request.user.groups.exists():
group = request.user.groups.all()[0].name
if group == 'GroupName':
return redirect('url')
if group == 'admin':
return view_func(request, *args, **kwargs)
return wrapper_function
views.py
def createuser(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
user = form.save()
username = form.cleaned_data.get('username')
group = Group.objects.get(name='GroupName')
user.groups.add(group)
Customer.objects.create(
user=user, )
messages.success(request, 'Account was created for ' + username)
return redirect('login')
context = {'form': form}
return user
on your views.py you add #allowed_users(allowed_roles=['GROUPNAME'])
for the permission, that group see the following things
I just add some lines of code to Views.py when i add a user:
def createView(request):
form=FormAddAccount()
if request.method=="POST":
form=FormAddAccount(request.POST)
if form.is_valid():
user=form.save()
for element in form.cleaned_data["groups"] :
group = Group.objects.get(name=element)
user.groups.add(group)
user.save()
redirect("accounts/list.html")
context={
'form':form
}
return render(request,"accounts/addaccount.html",context)
I'm trying to make a Login but it doesn't work.
the error is
form.is_valid() return False and
'LoginForm' object has no attribute 'cleaned_data'
I can't figure out out is the problem.
user/forms.py
class LoginForm(forms.Form):
email = forms.EmailField(widget=forms.EmailInput(
attrs={'style': 'width:100%; height:100%;'}))
password = forms.CharField(widget=forms.PasswordInput(
attrs={'style': 'width:100%; height:100%;'}))
def __init__(self, request=None, *args, **kwargs):
self.request = request
super(LoginForm, self).__init__(*args, **kwargs)
self.fields['email'].label = "이메일"
self.fields['password'].label = "비밀번호"
def clean(self):
super().clean()
email = self.cleaned_data.get("email")
password = self.cleaned_data.get("password")
try:
user = models.User.objects.get(email=email)
if user.check_password(password):
return self.cleaned_data
else:
self.add_error("password", forms.ValidationError(
"비밀번호가 틀렸습니다."))
except models.User.DoesNotExist:
self.add_error("email", forms.ValidationError(
"존재하지 않는 계정입니다."))
users/views.py
class LoginView(mixins.LoggedOutOnlyView, View):
def get(self, request):
form = forms.LoginForm(request.POST)
return render(request, "users/login.html", {"form": form})
def post(self, request):
form = forms.LoginForm(request.POST or None)
print(form.is_valid())
if form.is_valid():
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
get_user_name = user_models.User.objects.get(email=email)
user = authenticate(
request, username=get_user_name, password=password)
if user is not None:
login(request, user)
return redirect(reverse("cores:home"))
else:
return render(request, "users/login.html", {"form": form})
You need to set a local variable with the return value of the super() call. In your fields you'd no longer call the self.cleaned_data variant but the local variable cleaned_data. Also return the cleaned_data at the end of the def clean() method - even if errors occurred.
def clean(self):
cleaned_data = super().clean()
email = cleaned_data.get("email")
password = cleaned_data.get("password")
...
# Don't forget to return the cleaned_data after everything
return cleaned_data
This is documented in the django docs:
https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
I have a RegisterForm that inherits from ModelForm with RegisterView that inherits from FormView. If every field data is valid, the user gets successfully created and is redirected to login page. But if there is a validation error, it shows the field error below that field and the form gets refreshed and all the fields data is lost. How to avoid form refreshing so that user need not to fill the details again and again.
forms.py
class RegisterForm(forms.ModelForm, PasswordValidatorMixin):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField( label='Confirm password', widget=forms.PasswordInput)
class Meta:
model = UserModel
fields = (
'first_name',
'last_name',
'username',
'password1',
'password2',
'current_email',
)
def __init__(self, social_email=None, social_fname=None, social_lname=None,
social_uname=None,*args, **kwargs):
super(RegisterForm, self).__init__(*args, **kwargs)
self.current_email = None
self.social_email = social_email
self.social_fname = social_fname
self.social_lname = social_lname
self.social_uname = social_uname
def clean(self, *args, **kwargs):
username = self.cleaned_data.get('username')
self.current_email = self.cleaned_data.get('current_email')
if self.social_email:
self.current_email = self.social_email
if not username:
raise forms.ValidationError({"username":"Username can't be empty"})
if not self.current_email:
raise forms.ValidationError({"current_email":"Email can't be empty"})
qs = UserModel.objects.filter(username=username)
qs_email = UserModel.objects.filter(current_email=self.current_email)
if qs.exists():
raise forms.ValidationError({"username":"Username is already taken"})
if qs_email.exists():
raise forms.ValidationError({"current_email":"Email has already been registered"})
return self.cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
current_email = self.cleaned_data.get('current_email')
password = self.cleaned_data.get('password1')
user.set_password(password)
if self.social_email:
user.is_active = True
user.save()
return user
views.py
class RegisterView(ContextMixin, FormView):
form_class = RegisterForm
template_name = 'accounts/register.html'
title = 'Register'
#method_decorator(sensitive_post_parameters('password'))
#method_decorator(csrf_protect)
#method_decorator(never_cache)
def dispatch(self, *args, **kwargs):
self.kwargs['social_email'] = SOCIAL_USER_EMAIL
self.kwargs['social_fname'] = SOCIAL_USER_FNAME
self.kwargs['social_lname'] = SOCIAL_USER_LNAME
if SOCIAL_USER_EMAIL:
self.kwargs['social_uname'] = SOCIAL_USER_EMAIL.split('#',1)[0]
return super(RegisterView, self).dispatch(*args, **kwargs)
# Passes view kwargs to html
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
if SOCIAL_USER_EMAIL:
context['social_email'] = self.kwargs['social_email']
context['social_fname'] = self.kwargs['social_fname']
context['social_lname'] = self.kwargs['social_lname']
context['social_uname'] = self.kwargs['social_uname']
# context['social_image'] = SOCIAL_USER_IMAGE
return context
# Passes view kwargs to form
def get_form_kwargs(self):
kwargs = super(RegisterView, self).get_form_kwargs()
kwargs.update(self.kwargs)
return kwargs
def form_valid(self, form):
form.save()
if not self.kwargs['social_email']:
return render(self.request, 'accounts/success.html', {
'title':"You've registered successfully",
'body':"You've successfully registered at antef! Please verify the link sent at " +
form.current_email
})
return render(self.request, 'accounts/success.html', {
'title':"You've registered successfully",
'body':"You've successfully registered with your " + self.kwargs['social_email'] + " account."})
First, you don't need validation error for empty inputs, just add required = True in your forms.py or in your model.
Second you are not returning anything after validation error, which making your form empty after refresh.
You can also check email and username separately, for better use,
def clean_email(self):
email = self.cleaned_data.get('email')
if your_condition:
raise forms.ValidationError()
return email
def clean_username(self):
username = self.cleaned_data.get('username')
if your_condition
raise forms.ValidationError
return username
After creating a UserProfile model. I started to create login but I'm stuck because of get_user() error.
EXCEPTION
AttributeError: 'LoginForm' object has no attribute 'get_user'
Here are my codes:
UPDATE
class LoginView(FormView):
form_class = LoginForm
redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'login.html'
success_url = '/'
def form_valid(self, form):
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None:
if user.is_active:
login(self.request, user)
return HttpResponseRedirect(self.get_success_url())
else:
return self.form_invalid()
def form_invalid(self):
return HttpResponseRedirect(reverse('accounts:login'))
def get_success_url(self):
if self.success_url:
redirect_to = self.success_url
else:
redirect_to = self.request.REQUEST.get(self.redirect_field_name, '')
netloc = urlparse.urlparse(redirect_to)[1]
if not redirect_to:
redirect_to = settings.LOGIN_REDIRECT_URL
elif netloc and netloc != self.request.get_host():
redirect_to = settings.LOGIN_REDIRECT_URL
return redirect_to
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid()
How to fix this? Any help would be appreciated. I'm really new on Django 1.5. Need help.
[update]
In the original code, the author is doing the authenticate stuff inside a form method called get_user. You are doing it outside the form already, so just replace form.get_user()with user.
I use a login view that is not class based, and I don't even care into using a Django form instance, but it should be easy to adapt:
def signin(request):
if request.method == 'POST':
user = authenticate(
email=request.POST.get('username', '').lower().strip(),
password= request.POST.get('password', ''),
)
if user is None:
messages.error(request, u'Invalid credentials')
else:
if user.is_active:
login(request, user)
return HttpResponseRedirect(request.GET.get('next', '/'))
else:
messages.error(request, u'User is not active.')
return render_to_response('login.html', locals(),
context_instance=RequestContext(request))
[old answer]
Define a get_user method for your form.
Untested (but should get you in the right path):
def get_user(self):
from django.contrib.auth import authenticate
return authenticate(
email=self.cleaned_data.get('username', '').lower().strip(),
password=self.cleaned_data.get('password', ''),
)