المالك وحده يعدّل
جزء من قسم المستخدمون والحسابات في رحلة Django على Coddy. الدرس 11 من 16.
أصبحت صفحة الملاحظة آمنة الآن، لكن صفحتي تعديلها وحذفها ليستا كذلك: لا يزال المساران /3/edit/ و/3/delete/ يفتحان أي ملاحظة. والأسوأ أنه لا حاجة إلى فتحهما أصلًا. فالنموذج يرسل طلب POST، ويمكن لأي شخص إرسال طلب POST إلى /3/delete/ من دون أن يرى الصفحة مطلقًا.
لذا، تُطبَّق القاعدة على كل عرض، لا على الصفحة التي تنشئ رابطًا إليها: كل عرض يحمّل صفًا باستخدام رقمه يحدد هناك من يُسمح له بتحميله. انظر إلى موضع الاستعلام في عرض يتعامل مع كل من GET وPOST:
def ticket_close(request, pk):
ticket = ... # عملية البحث: تُنفَّذ مع كل طلب
if request.method == "POST":
ticket.closed = True
ticket.save()
return redirect("tickets:list")
return render(request, "tickets/close.html", {"ticket": ticket})يُنفَّذ السطر الأول قبل فرع if request.method == "POST". إذا كان ذلك الاستعلام يتحقق أيضًا من المالك، فسيحصل الغريب على خطأ 404 عند طلب GET وطلب POST، ولن يتغير شيء.
التحدي
سهلفي notes/views.py، اجعل note_edit وnote_delete يرفضان الملاحظات التي لا يملكها المستخدم. ستُظهر ملاحظة مستخدم آخر خطأ 404 هناك، لكلٍّ من GET وPOST، وستبقى كما هي. أما ملاحظاتك، فستظل قابلة للتعديل والحذف.
سجّل الدخول باسم bob (كلمة المرور coddy-pass-123) وافتح /1/edit/: صفحة 404 غير موجودة.
جرّب بنفسك
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import get_object_or_404, redirect, render
from .forms import NoteForm
from .models import Note
def note_list(request):
notes = Note.objects.filter(owner=request.user)
return render(request, "notes/note_list.html", {"notes": notes})
def note_detail(request, pk):
note = get_object_or_404(Note, pk=pk, owner=request.user)
return render(request, "notes/note_detail.html", {"note": note})
def note_create(request):
if request.method == "POST":
form = NoteForm(request.POST)
if form.is_valid():
note = form.save(commit=False)
note.owner = request.user
note.save()
return redirect("notes:detail", pk=note.pk)
else:
form = NoteForm()
return render(request, "notes/note_form.html", {"form": form})
def note_edit(request, pk):
note = get_object_or_404(Note, pk=pk)
if request.method == "POST":
form = NoteForm(request.POST, instance=note)
if form.is_valid():
form.save()
return redirect("notes:detail", pk=note.pk)
else:
form = NoteForm(instance=note)
return render(request, "notes/note_form.html", {"form": form, "note": note})
def note_delete(request, pk):
note = get_object_or_404(Note, pk=pk)
if request.method == "POST":
note.delete()
return redirect("notes:list")
return render(request, "notes/note_confirm_delete.html", {"note": note})
@login_not_required
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect("notes:list")
else:
form = UserCreationForm()
return render(request, "notes/signup.html", {"form": form})
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس المستخدمون والحسابات
تدرّب بنفسك: Playground لـ Django