Only the Poster Edits
Part of the Class-Based Views section of Coddy's Django journey. Lesson 16 of 18.
Log in as grace and open /jobs/python-developer-brightline/edit/: ada posted that job, and grace can change it. Job pages show Edit only to the poster, but anyone can type the address or send a POST, so the view itself must refuse.
UserPassesTestMixin calls a method you write, test_func(), before the view runs. True lets the request through; False answers 403 Forbidden to a logged-in user, on GET and POST alike. A recipe site lets nobody change a published recipe:
class RecipeUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Recipe
fields = ["title", "minutes"]
def test_func(self):
return not self.get_object().publishedThe test runs before the view has looked the row up, so self.object does not exist yet. self.get_object() finds the row from the URL, the way the view will.
Challenge
MediumOnly a job's poster may edit or delete it:
- Add
UserPassesTestMixintoJobUpdateViewandJobDeleteView, afterLoginRequiredMixin. - The test passes only for the user who posted the job. Anyone else gets
403 Forbidden, on GET and POST.
Press Run, log in as grace and open the edit page above.
Try it yourself
from django.contrib.auth.mixins import LoginRequiredMixin
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(LoginRequiredMixin, CreateView):
model = Job
fields = ["title", "company", "city", "salary", "description"]
def form_valid(self, form):
form.instance.posted_by = self.request.user
return super().form_valid(form)
class JobUpdateView(LoginRequiredMixin, UpdateView):
model = Job
fields = ["title", "company", "city", "salary", "description"]
class JobDeleteView(LoginRequiredMixin, DeleteView):
model = Job
success_url = reverse_lazy("jobs:list")
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Class-Based Views
4Editing Views
CreateViewLanding on the New JobPractice on your own: Django playground