Skip to content

Instantly share code, notes, and snippets.

@Alexx-G
Last active January 24, 2022 14:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Alexx-G/a8ae10690760b3238043 to your computer and use it in GitHub Desktop.
Save Alexx-G/a8ae10690760b3238043 to your computer and use it in GitHub Desktop.
Login redirect with user friendly alerts
{% for message in messages %}
{# Login redirect alert.#}
{# We have to display only the last message. Other are irelevant, but must be iterated #}
{% if 'login_required' in message.tags and forloop.last %}
<div class="alert alert-info alert-dismissible fade in" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{ message }}
</div>
{% endif %}
{% endfor %}
'''
This module provides login required mixin for Class-Based Views.
This mixin allows to display a custom message for usser after redirect (in template).
To pass messages between views is used `django.contrib.messages` framework (https://docs.djangoproject.com/en/1.9/ref/contrib/messages/)
'''
from urllib.parse import urlparse
from django.contrib import messages
from django.shortcuts import resolve_url
from django.contrib.auth.views import redirect_to_login
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.conf import settings
class LoginRequiredMixin(object):
'''
Simple mixin to redirect unauthenticated users to login page.
If in subclass `login_alert_message` is overidden it will
be added to `django.contrib.messages` with tag `login_required`
and level `django.contrib.messages.INFO`
'''
login_alert_message = None
message_tags = 'login_required'
message_level = messages.INFO
# login_alert_message = _('You need to login to view this page.')
def get_login_url(self):
'''
Override this to provide differend login url.
'''
return settings.LOGIN_URL
def login_redirect(self, request):
'''
Performs login redirect. Basically, should return a redirect response.
Based on `user_passes_test` decorator from django library.
'''
path = request.build_absolute_uri()
resolved_login_url = resolve_url(self.get_login_url())
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
return redirect_to_login(
path, resolved_login_url, REDIRECT_FIELD_NAME
)
def is_authenticated(self, request):
'''
Override this if you want to change default behaviour.
Returns: True/False
'''
return request.user.is_authenticated()
def dispatch(self, request, *args, **kwargs):
if self.is_authenticated(request):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
if self.login_alert_message:
messages.add_message(
request,
self.message_level,
self.login_alert_message,
extra_tags=self.message_tags,
fail_silently=True
)
return self.login_redirect(request)
from django.utils.translation import ugettext_lazy as _
from .mixins import LoginRequiredMixin
class ProductDetailsView(LoginRequiredMixin, View):
login_alert_message = _(
'You need to login to view more information for this product'
)
# other attributes are irelevant
class PersonInfoView(LoginRequiredMixin, View):
login_alert_message = _(
'You have to login to access premium info'
)
# other attributes are irelevant
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment