[Answered ]-Django Class Based View: Deny access to future dates unless logged in

1👍

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')

Leave a comment