How To Properly Customize Django LoginView
To answer your question, let me suppose you have a client model, in a way, similar to this model, and we'll need a helper models that stores the user's logins:
models.py:
from django.db import models
from django.contrib.auth.models import User
class Client(models.Model):
"""
This client model is pointing to django's User model
You can use your custom user model using AbstractBaseUser or whatever.
And if you're using django's User model directly, this class is not required
"""
user = models.OneToOneField(
User,
on_delete=models.DO_NOTHING,
verbose_name='User',
related_name='cli', # related name manager if needed
null=False,
blank=False,
)
def __str__(self):
return '{}'.format(self.user.username)
class ClientLogins(models.Model):
"""
This is a helper model table that stores the logins dates of the client
"""
client = models.ForeignKey(
Client,
verbose_name='Client',
on_delete=models.DO_NOTHING
)
date = models.DateTimeField(verbose_name="Date login")
def __str__(self):
return '{}'.format(self.client)
Then your form:
forms.py:
class LoginForm(forms.ModelForm):
'''Simple login form'''
class Meta:
model = User
fields = ('username', 'password')
And finally, your login behaviour should be treated in the views classes/functions.
views.py:
from datetime import timedelta
from django.utils import timezone
from MY_APP import models, forms
class LoginUser(LoginView):
template_name = 'login.html' # your template
from_class = forms.LoginForm # your form
def get_success_url(self):
'''Here the part where you can implement your login logic'''
now = timezone.now()
# Get current day date object
# like: 12/02/2019 00:00:00
today = now.replace(minute=0).replace(second=0).replace(microsecond=0)
# Get the client from the user object
client = self.request.user.cli
# Get all the user today's logins and count them
client_logins = models.ClientLogins.objects.filter(
client=client,
date__gte=today,
date__lte=today + timedelta(days=1)
).count()
if client_logins < 1: # Or: if not client_logins:
# create a login tracker record
models.ClientLogins.objects.create(
client=client,
date=now # Store the date where the user logged in the website
)
return reverse_lazy('FIRST_LOGIN_REDIRECT_URL')
# Or redirect to: settings.LOGIN_REDIRECT_URL
return super().get_success_url()
And for more informations, this is the core code of LoginView
, like this you can know the MRO
list and what you can override to have your desired behaviour.
Steve Smith
Updated on June 04, 2022Comments
-
Steve Smith almost 2 years
I am trying to figure out how to customize the django LoginView based on whether or not it's the user's first time logging on for the day. I have my LoginView currently set up so that it defaults to the LOGIN_REDIRECT_URL = "book:author" in my settings.py file. This works flawlessly. When a user logins in and is successfully authenticated, they are redirected to "book:author" as I would expect.
What I'm trying to do is if this is the first time the user has logged in for the day, direct them to one URL, and if it's any other login iteration for the day, redirect them to a different URL. I have read about various methods on how to do this, to use messaging as opposed to conditional URL redirect to using the NEXT parameter and I'm trying to figure out which is the best and most secure and proper way of going about this.
Here is my default LoginView...( Nothing fancy )
class LoginView(LoginView): template_name = 'registration/login.html' form_class = AuthenticationForm
And then it redirects based on my settings.py file definition...
LOGIN_REDIRECT_URL = "book:author"
What is the best way to redirect for first login of the day to different URL?
Thanks in advance for any suggestions.
I found this SO answer Django -- Conditional Login Redirect and it seems to be what I'm looking for. Are there any downsides to using the example at the bottom?
And how to do with a LoginView as opposed to the function based example?