Django / سير تطبيق موثوق / الدرس 10
الصلاحيات ونطاق الكائن
طبق صلاحيات النموذج وقواعد المورد عند حد العرض الموثوق قبل القراءة والتغيير.
في هذه الصفحة
أهداف الدرس
- تسمية الممثل والعملية والمورد
- قاعدة ملكية صغيرة قابلة للاختبار
- إثبات المنع دون آثار جزئية
تسمية الممثل والعملية والمورد
يقرر التفويض فعل ممثل على مورد بسياقه ولا تمنح المصادقة إذنا شاملا. تعبر الصلاحيات والمجموعات عن قدرات، ولا تعني صلاحية change العامة ملكية كل سجل. حدد المستأجر والمؤلف والنشر والدور عند الصلة، واجمع القاعدة وافرضها على المباشر لا الأزرار المخفية. لا تمنع قائمة التنقل الطلب المصنوع. وقد تكون صلاحية تغيير نوع من السجلات أوسع أو أضيق من ملكية سجل بعينه، لذلك يجب أن يوضح العقد كيف تتفاعل القدرتان في المجال.
فهم ضمان الخلفية المختارة
تعرض Django واجهات تقبل كائنا لكن ModelBackend الافتراضية لا تنفذ منظومة صفية كاملة؛ فلا تنشئ الوسيطة القاعدة. قد تضيف خلفية أو حزمة سلوكا ويجب حساب التجاوزات الفعلية. استخدم المستخدم المهيأ ولا تثبت أدوارا. حدد المنع أو الإخفاء كغياب بسياسة واختبرها باتساق دون كشف عرضي. وعند اختيار إخفاء المورد كأنه غير موجود، يجب اختبار ذلك في جميع مسارات القراءة والتعديل حتى لا تكشف رسالة أو استجابة مختلفة وجوده عرضيا.
قاعدة ملكية صغيرة قابلة للاختبار
يختبر البرنامج قاعدة نقية: مصادق ومعرف مالك مطابق. تعزل dataclasses ذلك بلا جدول وجلسة، ولا تدعي فرض الخلفية لها. يجب استدعاؤها أو تطبيق نطاق مكافئ بالهوية الموثوقة. اختبر المجهول ومصادقًا آخر كي لا يمر فحص الدخول وحده. ويجب أن يتضمن الاختبار مستخدما مصادقا لا يملك المورد، لأن الاقتصار على الضيف والمالك قد يفوت تنفيذا لا يفحص إلا تسجيل الدخول.
from django.conf import settings
settings.configure(
SECRET_KEY="synthetic-course-key",
USE_I18N=False, USE_TZ=True,
INSTALLED_APPS=[],
DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}},
DEFAULT_AUTO_FIELD="django.db.models.AutoField",
ALLOWED_HOSTS=["testserver"],
)
import django
django.setup()
from dataclasses import dataclass
@dataclass(frozen=True)
class Actor:
id: int | None
is_authenticated: bool
@dataclass(frozen=True)
class CourseRecord:
owner_id: int
def can_edit(actor, course):
return actor is not None and actor.is_authenticated and actor.id == course.owner_id
course = CourseRecord(owner_id=7)
print(can_edit(Actor(7, True), course))
print(can_edit(Actor(9, True), course))
print(can_edit(Actor(None, False), course))
True
False
False
توضح الدالة قاعدة ملكية صريحة ولا تسجلها Django تلقائيا.
تقييد النسخة قبل ربط نموذج الكتابة
يفترض المقطع النموذج وCourseForm والوسيط والمسارات وCSRF. يجلب من نطاق المستخدم قبل الربط، ويختار عمدا الغياب لمعرف غيره بدل كشفه ببحث عام. يكتب المقبول الحقول المعلنة فقط ولا ينفذ هنا. إذا تغير المالك متزامنا ويحتاج الالتزام ضمانا فنسقه بمعاملة لا قرار قديم. ولا يكفي القرار السابق إذا كان المالك قابلا للتغيير أثناء الكتابة وكان الثابت يتطلب اتساقا عند الالتزام؛ حينها يجب تنسيق العملية مع القاعدة.
from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect, render
from django.views.decorators.http import require_POST
from .forms import CourseForm
from .models import Course
@login_required
@require_POST
def update_course(request, course_id):
course = get_object_or_404(Course.objects.filter(owner=request.user), pk=course_id)
form = CourseForm(request.POST, instance=course)
if not form.is_valid():
return render(request, "catalog/course_form.html", {"form": form}, status=400)
course = form.save()
return redirect("course-detail", course_id=course.pk)
In the declared isolated app: non-owner id is not found; valid owner input updates approved fields only.
تخفي السياسة سجلات غيره بالبحث المقيد ويستبعد النموذج المالك ويحفظ CSRF.
إثبات المنع دون آثار جزئية
اختبر المجهول والمالك والآخر والمفقود والدور الحقيقي، وأكد الرد وبقاء المخزن فقد يكتب قبل المنع. تحتاج القائمة نطاقا؛ لا تبيح عملية العرض كل صف وداخلية. راجع التصدير والعلاقات والأخطاء. لا تجعل الجميع staff أو superuser لإصلاح الفشل، بل أصلح القاعدة والخلفية والنطاق واحفظ السالب. ويشمل نطاق المراجعة الحقول الداخلية والتصدير والأخطاء، لا الصفحة الرئيسية فقط، لأن البيانات الخاصة قد تتسرب من رد مساعد رغم حماية العرض الأصلي.
الأخطاء الشائعة وإصلاحها
تعد change فرضا للملكية
- لماذا يحدث؟
- اختلطت قدرة النموذج والصف.
- كيف تصلحه؟
- نفذ النطاق أو الخلفية المناسبة.
- كيف تتجنب تكراره؟
- اختبر مصادقا آخر.
يبقى التغيير رغم المنع
- لماذا يحدث؟
- فُوض بعد الكتابة.
- كيف تصلحه؟
- افحص الوصول قبل الكتابة.
- كيف تتجنب تكراره؟
- أكد حفظ الحالة.
يسرب التصدير علاقات خاصة
- لماذا يحدث؟
- رُوجعت الصفحة فقط.
- كيف تصلحه؟
- قيد السجلات والحقول الداخلية.
- كيف تتجنب تكراره؟
- ضم التصدير والأخطاء للاختبار.
اختبر فهمك
1. لماذا لا يكفي إخفاء زر التعديل؟
اعرض الحل المشروح
يمكن إرسال الطلب مباشرة. صادق وفوض بالخادم ثم تحقق واكتب المسموح، واجعل الإخفاء عرضا مفيدا لا سلطة الوصول.
2. أي تأكيد يميز المنع من كتابة ثم منع؟
اعرض الحل المشروح
أكد الرد وأعد قراءة القيم والملك الأصليين، واختبر نجاح المالك كي لا يمر رفض الجميع. ينتمي الطرفان للعقد.
أهم ما تعلمته
- القدرة ونطاق الكائن مختلفان.
- افرض الوصول قبل التعديل.
- اختبر المسموح وحدود المنع.