Menu
CoddyTech

لا يحرر إلا ناشر الإعلان

جزء من قسم واجهات العرض المعتمدة على الأصناف في رحلة Django على Coddy. الدرس 16 من 18.

سجّل الدخول باسم grace وافتح /jobs/python-developer-brightline/edit/: نشرت ada إعلان الوظيفة هذا، ويمكن لـ grace تعديله. تعرض صفحات الوظائف Edit للناشر فقط، لكن يمكن لأي شخص كتابة العنوان أو إرسال طلب POST، لذلك يجب أن يرفض العرض نفسه الطلب.

يستدعي UserPassesTestMixin طريقة تكتبها أنت، وهي test_func()، قبل تشغيل العرض. عندما تُرجع True، يمر الطلب. وعندما تُرجع False، يتلقى المستخدم الذي سجّل الدخول استجابة 403 Forbidden، سواء كان الطلب GET أو POST. يتيح موقع وصفات الطعام لأي شخص تغيير وصفة منشورة:

class RecipeUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Recipe
    fields = ["title", "minutes"]

    def test_func(self):
        return not self.get_object().published

يُجرى الاختبار قبل أن يبحث العرض عن الصف، لذا لا تكون self.object موجودة بعد. تعثر self.get_object() على الصف من عنوان URL، بالطريقة نفسها التي سيتبعها العرض.

challenge icon

التحدي

متوسط

لا يجوز تعديل الوظيفة أو حذفها إلا لمن نشرها. في jobs/views.py، أضف UserPassesTestMixin إلى JobUpdateView وJobDeleteView، بعد LoginRequiredMixin. لا ينجح الاختبار إلا للمستخدم الذي نشر الوظيفة، وسيحصل أي شخص آخر على 403 Forbidden عند استخدام GET وPOST.

سجّل الدخول باسم grace (coddy-pass-123) وافتح /jobs/python-developer-brightline/edit/: لقد نشرتها ada، لذا سترى 403 Forbidden.

جرّب بنفسك

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")
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس واجهات العرض المعتمدة على الأصناف

تدرّب بنفسك: Playground لـ Django