LoginRequiredMixin
Part of the Class-Based Views section of Coddy's Django journey. Lesson 14 of 18.
Right now anyone can post, edit or delete a job without an account. A class has no single function to put @login_required on, so Django gives you a mixin: a small class you add to a view's parents for one extra behaviour.
from django.contrib.auth.mixins import LoginRequiredMixin
class RecipeCreateView(LoginRequiredMixin, CreateView):
model = Recipe
fields = ["title", "minutes"]A logged-out visitor is now sent to /accounts/login/?next=/recipes/new/ before the view runs, on GET and POST alike. After logging in, next brings them back.
The mixin goes first. Every view starts in a method called dispatch(), and Python looks for it in the parents from left to right. Written (CreateView, LoginRequiredMixin), the view's own dispatch() wins, the login check never runs, and nothing warns you.
Challenge
MediumOnly logged-in users may post, edit or delete jobs:
- Add
LoginRequiredMixintoJobCreateView,JobUpdateViewandJobDeleteView. - The jobs list and the job pages stay open to everyone.
Press Run and press Post a job: you land on the login page. Log in as ada, password coddy-pass-123.
Try it yourself
from django.urls import reverse_lazy
from django.views.generic import CreateView, DeleteView, DetailView, ListView, TemplateView, UpdateView
from .models import Job
class HomeView(TemplateView):
template_name = "jobs/home.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["count"] = Job.objects.count()
context["latest"] = Job.objects.order_by("-posted").first()
return context
class AboutView(TemplateView):
template_name = "jobs/about.html"
class JobListView(ListView):
model = Job
context_object_name = "jobs"
ordering = ["-posted"]
paginate_by = 5
def get_queryset(self):
jobs = super().get_queryset()
city = self.request.GET.get("city")
if city:
jobs = jobs.filter(city=city)
return jobs
class JobDetailView(DetailView):
model = Job
class JobCreateView(CreateView):
model = Job
fields = ["title", "company", "city", "salary", "description"]
class JobUpdateView(UpdateView):
model = Job
fields = ["title", "company", "city", "salary", "description"]
class JobDeleteView(DeleteView):
model = Job
success_url = reverse_lazy("jobs:list")
All lessons in Class-Based Views
4Editing Views
CreateViewLanding on the New JobPractice on your own: Django playground