
پستهای وبلاگ معمولاً به ترتیب زمانی معکوس (از جدید به قدیم) نمایش داده میشوند، به طوری که جدیدترین پستها ابتدا مشاهده شوند. ما برای مدل خود، یک ترتیب پیشفرض (Default Ordering) تعریف خواهیم کرد. این ترتیب هنگام بازیابی (Retrieving) اشیاء از پایگاه داده اعمال میشود، مگر اینکه در کوئری (Query) خاصی، ترتیب متفاوتی تعیین شده باشد.
فایل models.py در اپلیکیشن blogرا مطابق قطعه کد زیر ویرایش کنید:
from django.db import models from django.utils import timezone class Post(models.Model): title = models.CharField(max_length=250) slug = models.SlugField(max_length=250) body = models.TextField() publish = models.DateTimeField(default=timezone.now) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: ordering = ['-publish'] def __str__(self): return self.title
ما یک کلاس Meta در داخل مدل اضافه کردهایم. این کلاس، متادادهها (Metadata) مربوط به مدل را تعریف میکند. ما از ویژگی (Attribute) ordering استفاده میکنیم تا به جنگو بگوییم که نتایج را بر اساس فیلد publish مرتب کند. این ترتیب مرتبسازی، بهصورت پیشفرض برای کوئریهای دیتابیس اعمال خواهد شد، مگر اینکه ترتیب خاص دیگری در خودِ کوئری تعیین شده باشد. ما با استفاده از یک خط تیره (-) قبل از نام فیلد (-publish)، ترتیب نزولی (Descending) را مشخص میکنیم. در نتیجه، پستها بهصورت پیشفرض با ترتیب زمانی معکوس (از جدید به قدیم) بازگردانده خواهند شد.
بیایید یک ایندکس پایگاه داده برای فیلد publish تعریف کنیم. این کار باعث بهبود عملکرد (Performance) در هنگام فیلتر کردن کوئریها یا مرتبسازی نتایج بر اساس این فیلد میشود. باتوجه به اینکه نتایج را به صورت پیشفرض بر اساس فیلد publish مرتب میکنیم درنتیجه کوئریهای خیلی زیادی از این ایندکس استفاده میکنند و باعث افزایش سرعت کوئری میشود.
فایل models.py در اپلیکیشن blog را مطابق الگوی زیر ویرایش کنید:
from django.db import models from django.utils import timezone class Post(models.Model): title = models.CharField(max_length=250) slug = models.SlugField(max_length=250) body = models.TextField() publish = models.DateTimeField(default=timezone.now) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) class Meta: ordering = ['-publish'] indexes = [ models.Index(fields=['-publish']), ] def __str__(self): return self.title
ما گزینه indexes را به کلاس Meta مدل اضافه کردهایم. این گزینه به شما اجازه میدهد ایندکسهای پایگاه داده را برای مدل خود تعریف کنید؛ این ایندکسها میتوانند شامل یک یا چند فیلد، با ترتیب صعودی یا نزولی، و یا حتی عبارات عملکردی (Functional Expressions) و توابع دیتابیس باشند. ما یک ایندکس برای فیلد publish اضافه کردیم. با استفاده از یک خط تیره قبل از نام فیلد، ایندکس را مشخصاً با ترتیب نزولی(ِDecsending) تعریف کردهایم. فرآیند ایجاد این ایندکس، در عملیات مهاجرت پایگاه داده (Database Migrations) که در مراحل بعد برای مدلهای وبلاگ خود ایجاد میکنیم، گنجانده خواهد شد.
نکته مهم: قابلیت تعیین ترتیب (Ordering) در ایندکس، در MySQL پشتیبانی نمیشود. اگر از MySQL به عنوان پایگاه داده استفاده میکنید، یک ایندکس نزولی در واقع به صورت یک ایندکس معمولی (صعودی) ساخته خواهد شد.
اکنون وقت آن رسیده که اپلیکیشن خود را جهت فعالسازی در پروژهمان به سیستم جنگو معرفی شود.
این کار باعث میشود جنگو پیگیر تغییرات اپلیکیشن باشد و همچنین بتواند جداول پایگاه داده را بر اساس مدلها بسازد.
برای این کار باید فایل settings.py را ویرایش کنید و آیتم "blog.apps.BlogConfig" را به لیستی تحت عنوان INSTALLED_APPS اضافه کنید: مانند نمونه کد زیر:

کلاس BlogConfig تنظیمات مربوط به این اپلیکیشن را مشخص میکند. با این کار جنگو متوجه میشود که این اپلیکیشن در این پروژه فعال شده است و از این پس میتواند مدلهای آن را بارگزاری کند.
یکی از قابلیتهای رایج در وبلاگها این است که نوشتهها تا زمانی که آماده انتشار شوند، به صورت پیشنویس (Draft) ذخیره شوند. ما یک فیلد status به مدل خود اضافه میکنیم که به ما اجازه میدهد وضعیت پستهای وبلاگ را مدیریت کنیم. برای پستها از دو وضعیت Draft و Published استفاده خواهیم کرد.
فایل models.py در اپلیکیشن blog را ویرایش کنید تا به شکل زیر درآید:

ما کلاس شمارشی (Enumeration) به نام Status را با ارثبری از models.TextChoices تعریف کردهایم. گزینههای موجود برای وضعیت پست عبارتاند از:
DRAFT
PUBLISHED
مقادیر آنها به ترتیب:
DF
PB
و نامهای نمایشی آنها به ترتیب:
Draft
Published
جنگو نوعهایی از enumeration ارائه میدهد که میتوانید از آنها ارثبری کنید تا گزینهها (choices) را به شکل سادهتری تعریف کنید. این نوعها بر پایه شیء enum در کتابخانه استاندارد پایتون ساخته شدهاند.
برای مطالعه بیشتر درباره enum میتوانید به این لینک مراجعه کنید:
https://docs.python.org/3/library/enum.html
نوعهای enumeration در جنگو چند تغییر نسبت به enum استاندارد دارند. درباره این تفاوتها میتوانید در مستندات جنگو مطالعه کنید:
https://docs.djangoproject.com/en/5.0/ref/models/fields/#enumeration-types
ما میتوانیم از ویژگیهای زیر استفاده کنیم:
Post.Status.choices
برای دریافت همه گزینههای قابل انتخاب
Post.Status.names
برای دریافت نام گزینهها
Post.Status.labels
برای دریافت نامهای نمایشی
Post.Status.values
برای دریافت مقادیر واقعی گزینهها
اکنون ما یک فیلد جدید به نام status به مدل اضافه کردهایم که از نوع CharField است. این فیلد شامل پارامتر choices است که مقدار آن را به گزینههای تعریفشده در Status محدود میکند.
همچنین با استفاده از پارامتر default یک مقدار پیشفرض برای این فیلد تعیین کردهایم. در اینجا مقدار پیشفرض DRAFT در نظر گرفته شده است.
یک روش خوب در طراحی مدلها این است که choices را داخل همان کلاس مدل تعریف کنید و از enumeration types استفاده کنید. این کار باعث میشود بتوانید در هر جای کد به راحتی به label، value یا name گزینهها دسترسی داشته باشید.
برای مثال میتوانید مدل Post را import کنید و در هر جای کد از مقدار زیر به عنوان مرجع وضعیت پیشنویس استفاده کنید:
Post.Status.DRAFT
بیایید ببینیم چگونه میتوان با status choices کار کرد.
دستور زیر را در ترمینال اجرا کنید تا Python shell باز شود:
python manage.py shell
سپس خطوط زیر را وارد کنید:
>>> from blog.models import Post >>> Post.Status.choices
در این حالت، گزینههای enum به صورت جفتهای مقدار و نام نمایشی (value-label pairs) نمایش داده میشوند، مانند:
[('DF', 'Draft'), ('PB', 'Published')]
خط زیر را وارد کنید:
Post.Status.labels
در این صورت، نامهای خوانا برای انسان (human-readable names) از اعضای enum را دریافت میکنید:
['Draft', 'Published']
خط زیر را وارد کنید:
Post.Status.values
در این حالت، مقادیر واقعی اعضای enum را دریافت خواهید کرد. اینها همان مقادیری هستند که در پایگاه داده برای فیلد status ذخیره میشوند:
['DF', 'PB']
خط زیر را وارد کنید:
Post.Status.names
در نتیجه، نام گزینهها (names) را دریافت میکنید:
['DRAFT', 'PUBLISHED']
همچنین میتوانید به یک عضو خاص از enumeration به این شکل دسترسی داشته باشید:
pythonPost.Status.PUBLISHED
و میتوانید به ویژگیهای آن نیز دسترسی پیدا کنید:
Post.Status.PUBLISHED.name
Post.Status.PUBLISHED.value
این ویژگیها به ترتیب نام عضو enum و مقدار واقعی آن را برمیگردانند.
پست قبلی: (فصل اول - اپیزود ۶ - ترجمه کتاب Django 5 By Example)
پست بعدی: (فصل اول - اپیزود 8 - رابطه یک به چند کاربر نویسنده به پستها و مایگرشن به دیتابیس)
کم کم داره جذاب میشه کتاب و پیشنهاد میکنم شمایی که تا اینجا همراه با من بودید، ادامه کتاب رو از دست ندید👍😉