I have a Promotion model containing a published_date field. I would like to restrict access to future promotions to logged in users who are 'previewing' their promotion.
class Promotion(models.Model):
title = models.CharField(max_length=100, blank=False, null=False)
...
promotion_date = models.DateField(blank=False, null=True)
At the moment I'm running a simple Class Based DetailView:
class PromotionDetailView(generic.DetailView):
model = Promotion
context_object_name = 'book'
template_name = 'PromoManager/book_detail.html'
But I am unsure how or when to intercept this request and add the condition for non logged in users to redirect if promotion_date is greater than today. I currently have simple_tag which returns a bootstrap alert highlighting future promotions but this is purely visual.
in_the_future = timezone.now().date()
if hasattr(book, 'promotion_date') and book.promotion_date > in_the_future:
return ...appropriate message...
If I was doing it via Function Based Views I would apprach it with an if statement combined with a redirect. I considered the same approach via DetailView/TemplateView and get_context_data but this doesn't feel right.
How can I best intercept the request and redirect the page for non-logged in users if the promotion_date is in the future?
You can just filter it out in get_queryset
:
from django.db.models import Q
from django.utils.timezone import now
class PromotionDetailView(generic.DetailView):
model = Promotion
context_object_name = 'book'
template_name = 'PromoManager/book_detail.html'
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
if not self.request.user.is_authenticated:
qs = qs.filter(Q(promotion_date=None) | Q(promotion_date__lte=now()))
return qs
this will thus limit the queryset to items that are not in the future, in case the user was logged in. The filtering also happens at the database side.
You can handle the 404 by overriding the dispatch
and thus perform a redirect in that case:
from django.db.models import Q
from django.http import Http404
from django.shortcuts import redirect
from django.utils.timezone import now
class PromotionDetailView(generic.DetailView):
model = Promotion
context_object_name = 'book'
template_name = 'PromoManager/book_detail.html'
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
if not self.request.user.is_authenticated:
qs = qs.filter(Q(promotion_date=None) | Q(promotion_date__lte=now()))
return qs
def dispatch(self, *args, **kwargs):
try:
return super().dispatch(*args, **kwargs)
except Http404:
return redirect('name-of-some-view')