مدل در جنگو
آنچه الان میخواهیم بسازیم چیزی است که تمام پستهای ما در وبلاگ را ذخیره میکند. اما برای اینکه بتوانیم این کار را بکنیم باید کمی در مورد مفهوم شیء
صحبت کنیم.
اشیاء
مفهومی در برنامه نویسی وجود دارد که به آن برنامهنویسی شیءگرا
گفته میشود. به این معنی که به جای آنکه همه چیز را در ردیفهایی طولانی از دستورات بنویسیم میتوانیم مدل هایی درست کنیم و تعریف کنیم که این مدل ها چگونه با هم ارتباط داشته باشند.
یک شیء چیست؟ یک شیء مجموعهای از خصوصیات و اعمال است. ممکن است کمی عجیب باشد اما برای شما مثالی خواهیم زد.
اگر بخواهیم مدلی برای یک گربه بسازیم یک شیء به نام Cat
میسازیم که دارای خصوصیاتی است مانند رنگ
، سن
، حالت
(مثلاً خوب، بد یا خوابآلود) و مالک
(که میتواند اشاره به یک شیء Person
یا در در مورد گربههای ولگرد، بدون اشاره به فردی خاص، خالی بماند).
یک شیء از نوع Cat
دارای فعالیتیهایی مانند: خُرخُر کردن
، خراشیدن
و یا غذا خوردن
است. (برخی مواقع به گربه، غذای گربه
میدهیم که میتواند یک شیء جداگانه باشد که خصوصیت مزه
داشته باشد).
Cat
--------
color
age
mood
owner
purr()
scratch()
feed(cat_food)
CatFood
--------
taste
بنابراین ایده اصلی آن است که چیزهای واقعی در کدها با خصوصیات (که به آن object properties
میگوییم) و اعمال (که به آن methods
میگوییم) تعریف شوند.
ما میخواهیم یک وبلاگ درست کنیم، درست است؟ چگونه یک مدل برای پستهای وبلاگی بسازیم؟
باید به این سوال پاسخ دهیم که: یک پست وبلاگی چیست؟ چه خصوصیاتی دارد؟
خب، پست وبلاگی ما قطعاً به مقداری متن و یک عنوان نیاز دارد، درست است؟ بسیار خوب خواهد بود که بدانیم چه کسی مطلب را نوشته است، پس به نویسنده هم احتیاج داریم. سرانجام میخواهیم بدانیم که این مطلب در چه تاریخی نوشته و منتشر شده است.
Post
--------
title
text
author
created_date
published_date
چه کارهایی با یک پست وبلاگی میتوان انجام داد؟ بسیار جالب خواهد بود که متدهایی
داشته باشیم که بتواند یک پست را منتشر کند. چطور است؟
بنابراین به یک متد انتشار یا publish
نیاز داریم.
حالا که میدانیم دقیقاً به چه چیزی احتیاج داریم بیایید مدل سازی در جنگو را شروع کنیم!
مدل در جنگو
حالا که میدانیم شیء چیست، میتوانیم یک مدل جنگویی برای پستهای وبلاگمان بسازیم.
یک مدل در جنگو نوعی شیء ویژه است که در پایگاه داده
یا database ذخیره میشود. یک پایگاه داده مجموعهای از اطلاعات است. جایی است که در آن اطلاعات مربوط به کاربرها، پستهای وبلاگی و غیره را نگهداری میکنیم. ما از پایگاه داده SQLite برای ذخیره اطلاعات استفاده میکنیم. این پایگاه داده، پایگاه داده پیشفرض در جنگو است و الان برای ما کافی است.
شما میتوانید یک مدل را در پایگاه داده، چیزی شبیه به یک صفحه گسترده با ستونها (فیلدها) و ردیفها(دادهها) تصور کنید.
ساختن یک اپلیکیشن
برای آنکه همه چیز مرتب باشد ما یک برنامه مجزا (اپلیکیشن) در پروژه خود خواهیم ساخت. خوب است که همه چیز از ابتدا مرتب باشد. برای ساخت یک برنامه جدید باید دستور زیر را در خط فرمان اجرا کنیم (در پوشه djangogirls
و جایی که فایل manage.py
وجود دارد):
Mac OS X or Linux:
(myvenv) ~/djangogirls$ python manage.py startapp blog
Windows:
(myvenv) C:\Users\Name\djangogirls> python manage.py startapp blog
خواهید دید که یک پوشه جدید به نام blog
ساخته شده و شامل تعدادی فایل است. پوشهها و فایلها در پروژه ما باید شبیه به این باشد:
djangogirls
├── blog
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── manage.py
├── mysite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── myvenv
│ └── ...
└── requirements.txt
بعد از ساختن این برنامه، باید به جنگو بگوییم تا از آن استفاده کند. این کار را در فایل mysite/settings.py
انجام میدهیم -- این فایل را در ویرایشگر کد باز کنید. باید INSTALLED_APPS
را پیدا کنیم و دقیقاً بالای علامت [
در انتهای این بخش، خطی شامل 'blog.apps.BlogConfig',
را اضافه کنیم. پس در نهایت شبیه این خواهد بود:
mysite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog.apps.BlogConfig',
]
ساختن مدل برای پست وبلاگ
در فایل blog/models.py
ما تمام اشیائی را که به آن مدل Model
میگوییم تعریف میکنیم. اینجا فضایی است که پستهای وبلاگی را تعریف میکنیم.
فایل blog/models.py
را در ویرایشگر کد باز کنید، تمام محتویات آن را پاک کنید و کدهای زیر را در آن بنویسید:
blog/models.py
from django.conf import settings
from django.db import models
from django.utils import timezone
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(
default=timezone.now)
published_date = models.DateTimeField(
blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
مطمئن بشوید که در هر طرف
str
دوبار از کاراکتر_
استفاده کنید. از این قرارداد زیاد در پایتون استفاده میشود که به آن "dunder" هم میگویند که مخفف "double-underscore" است.
عجیب به نظر میرسد؟ نگران نباشید ما درباره عملکرد این خط ها توضیح خواهیم داد!
تمام خطوطی که با from
یا import
شروع میشوند خطوطی هستند که محتوایی را از یک فایل دیگر به این فایل اضافه میکنند. پس به جای آنکه یک محتوای یکسان را در هر فایل تکرار کنیم، میتوانیم از این الگو استفاده کنیم from ... import ...
.
class Post(models.Model):
– این خط مدل ما را تعریف میکند (که یک شیء
یا object است).
class
کلید واژهای است که نشان میدهد در حال تعریف کردن یک شیء هستیم.Post
نام مدل ما است. میتوانیم به آن نام متفاوتی بدهیم (اما نباید از کاراکترهای خاص و اسپیس استفاده کنیم). همیشه نام یک کلاس را با حروف بزرگ شروع کنید.models.Model
به این معنی است که Post یک مدل جنگویی است، بنابراین جنگو میداند که این مدل باید در پایگاه داده ذخیره شود.
حالا ویژگیهایی که در مورد آنها صحبت کردیم را اضافه میکنیم: title
، text
، created_date
، published_date
و author
. برای این کار باید ویژگیهای هرکدام از اینها را مشخص کنیم (آیا متن است؟ یا عدد؟ یا تاریخ؟ یا ارتباطی با یک شیء دیگر دارد، مثلا کاربر؟)
models.CharField
– این عبارت مشخص میکند که ویژگی مورد نظر از جنس متن با تعداد کاراکتر محدود است.models.TextField
– این عبارت برای اختصاص دادن متن با تعداد کاراکتر نامحدود است. به نظر برای متن پستهای وبلاگی مناسب است، درست است؟models.DateTimeField
– مشخص کننده تاریخ و زمان است.models.ForeignKey
– نشان دهنده ارتباط به یک مدل دیگر است.
ما همه قطعات کد را توضیح نخواهیم داد برای آنکه زمان بسیار زیادی میگیرد. اگر بخواهید اطلاعات بیشتری در مورد فیلدهای یک مدل و انواع آن بدانید باید نگاهی به مستندات جنگو بیندازید (https://docs.djangoproject.com/en/2.2/ref/models/fields/#field-types).
منظور از def publish(self):
چیست؟ این دقیقاً متد یا عملیات publish
(انتشار یک پست وبلاگی) است که قبلتر در مورد آن صحبت کردیم. عبارت def
نشان دهنده آن است که یک تابع یا متد تعریف شده است و publish
نام این تابع است. شما میتوانید نام این تابع را به دلخواه عوض کنید. برای نامگذاری متدها، معمولاً از حروف کوچک و خط زیرین (underscore) به جای کاراکتر فاصله (space) استفاده میکنیم. برای مثال، تابعی که برای محاسبه قیمت متوسط لازم داریم به این صورت نامگذاری میشود calculate_average_price
.
توابع معمولاً یک مقدار را باز میگردانند که با return
تعریف میشود. نمونهای از این بازگرداندن در تابع __str__
وجود دارد. در این سناریو وقتی ما تابع __str__()
را فراخوانی میکنیم یک نوشته (با فرمت string) که حاوی عنوان پست وبلاگی است دریافت میکنیم.
همچنین توجه داشته باشید که هر دو تابع def publish(self):
و def __str__(self):
به کمک فاصلهگذاری ابتدای خط، درون کلاس تعریف شدهاند. چون پایتون به فاصلهها حساس است نیاز داریم که میزان فاصله ابتدا خط برای متدها درست تعریف شوند تا متد، درون کلاس قرار داشته باشد. در غیر اینصورت متدها عضوی از کلاس نخواهند بود، و ممکن است رفتار غیرمنتظرهای ببینید.
اگر هنوز چیزی در مورد مدلها برای شما مبهم است حتماً از مربی خود بپرسید! میدانیم که یادگرفتن مفاهیم اشیاء و توابع به طور همزمان، پیچیده است. ولی حداقل الان کمی برای شما واضحتر شده است!
ساختن جدول برای مدلها در پایگاه دادهها
آخرین مرحله این است که مدل جدیدی که ساختهایم را به پایگاه داده اضافه کنیم. ابتدا باید جنگو را از تغییراتی که در مدلها ایجاد کردهایم آگاه کنیم. (این تغییرات همین کارهایی است که انجام دادهایم!) به کنسول خط فرمان بروید و تایپ کنید python manage.py makemigrations blog
. چیزی شبیه این خواهید دید:
خط فرمان
(myvenv) ~/djangogirls$ python manage.py makemigrations blog
Migrations for 'blog':
blog/migrations/0001_initial.py:
- Create model Post
نکته: به یاد داشته باشید که فایلهایی که تغییر دادهاید را ذخیره کنید وگرنه ممکن است کامپیوتر نسخه قبلی فایل را در نظر بگیرد و پیغام خطا نشان بدهد.
جنگو یک فایل مهاجرت یا migration برای ما درست میکند که ما باید آن را به پایگاه داده ارسال کنیم. عبارت python manage.py migrate blog
را اجرا کنید و خروجی باید شبیه به این باشد:
خط فرمان
(myvenv) ~/djangogirls$ python manage.py migrate blog
Operations to perform:
Apply all migrations: blog
Running migrations:
Applying blog.0001_initial... OK
هورا! مدل Post ما اکنون در پایگاه داده قرار گرفته است! جالب خواهد بود که نگاهی به آن بیندازیم! پس به سراغ بخش بعدی بروید تا ببینید Post ها به چه صورتی درآمدهاند!