المالك وحده يعدّل
جزء من قسم المستخدمون والحسابات في رحلة 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/.
جرّب بنفسك
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