مشخصات مقاله
-
577
-
0.0
-
10466
-
0
-
0
استفاده از مدلها در جنگو Django
آموزش استفاده از مدلها در جنگو
این مقاله چگونگی تعریف مدلها را برای وب سایت LocalLibrary نشان میدهد. این مقاله توضیح میدهد که مدل چیست، چگونه توصیف میشود، و برخی از انواع اصلی آن کدامند. همچنین به طور خلاصه چند روش اصلی برای دسترسی به دادههای مدل را نشان میدهد.
پیش نیاز آموزش استفاده از مدلها در Django
آموزش ایجاد یک وب سایت skeleton
اهداف:
توانایی طراحی و ایجاد مدل های دلخواه، انتخاب فیلدهای متناسب
بررسی:
به دسترسی و مدیریت داده برنامههای وب Django از طریق اجزاء پایتون، مدل می گویند. مدلها، ساختار دادههای ذخیرهشده همچون انواع فیلد و احتمالا حداکثر اندازه، مقادیر پیشفرض، گزینههای فهرست انتخابی، متن کمکی برای مستندسازی، برچسب متنی برای فرم ها، و غیره را تعریف میکنند. تعریف یک مدل مستقل از پایگاه داده مرتبط با آن است – می توانید یکی را از میان چندین گزینه بعنوان بخشی از پروژه خود انتخاب کنید. هنگامی که پایگاهداده مورد نظر خود را انتخاب کردید، نیازی نیست مستقیما با آن ارتباط بگیرید - فقط ساختار مدل و دیگر کدها را مینویسید، و Django تمام کار برقراری ارتباط با پایگاهداده را برای شما انجام میدهد.
این آموزش، چگونگی تعریف و دسترسی به مدلها برای مثالِ وب WebSite LocalLibrary را نشان میدهد.
طراحی مدلهای LocalLibrary در Django
قبل از اینکه شروع به کدنویسی مدلها کنید، بهتر است چند دقیقه فکر کنید و مطمئن شوید که چه اطلاعاتی نیاز به ذخیره شدن دارند و روابط بین اجزاء مختلف چگونه باید باشد.
میدانیم که باید اطلاعات مربوط به کتاب¬ها را ذخیره کنیم (عنوان، خلاصه، مولف، زبان نوشتاری، گروه، ISBN) و اینکه ممکن است چندین کپی در دسترس داشته باشیم (با شناسه منحصر به فرد جهانی، وضعیت موجود بودن و غیره). شاید لازم باشد غیر از نام، اطلاعات بیشتری در مورد مولف ذخیره کنیم، و ممکن است چندین نویسنده با نامهای مشابه یا یکسان وجود داشته باشند. ما میخواهیم قادر باشیم اطلاعات را براساس عنوان کتاب، مولف، زبان نوشتاری و نوع کتاب مرتب کنیم.
زمانی که مدلهای خود را طراحی میکنید، منطقی است که مدلهای جداگانه ای برای هر "آبجکت" (گروهی از اطلاعات مرتبط) داشته باشید. در این مورد، آبجکت های بدیهی کتاب، نمونههای کتاب و نویسندگان هستند.
همچنین ممکن است بخواهید از مدلهایی استفاده کنید که گزینههای لیست انتخابی را نمایش دهند (به عنوان مثال، فهرست کرکرهای(Drop Down) گزینهها)، و آن را به جای ایکنه گزینه ها را با استفاده از کدنویسی در خود وب سایت تعریف کنید، بکار بگیرید– این تکنیک زمانی توصیه میشود که همه گزینهها در یک خط شناخته نمیشوند یا ممکن است تغییر کنند. در این حالت، گزینه¬های آشکار موجود برای مدل ها، شامل سبک کتاب (به عنوان مثال علمی - تخیلی، شعر فرانسوی و غیره) و زبان (انگلیسی، فرانسوی، ژاپنی) است.
هنگامی که در مورد مدلها و فیلد آن تصمیم گرفتیم، باید در مورد روابط فکر کنیم. Django به شما اجازه میدهد تا روابطی را تعریف کنید که یک به یک (OneToOneField)، یک به چند (ForeignKey) و چند به چند (ManyToManyField) هستند.
با توجه به این موضوع، نمودار ارتباط UML زیر مدلهایی را نشان میدهد که ما در این مورد و بصورت Box تعریف خواهیم کرد.

ما مدلهایی را برای کتاب (جزییات عمومی کتاب)، نمونه کتاب (وضعیت نسخههای فیزیکی خاص کتاب موجود در سیستم) و نویسنده ایجاد کردهایم. ما همچنین تصمیم گرفتهایم یک مدل برای ژانر داشته باشیم به طوری که بتوان مقادیر را از طریق واسط admin ایجاد/انتخاب کرد. ما همچنین تصمیم گرفتیم مدلی برای BookInstance:status نداشته باشیم. ما مقادیر را به صورت کد ثابت (LOAN_STATUS) نوشتیم، زیرا انتظار نداریم که تغییر کنند. در هر یک از جعبهها، میتوانید نام مدل، نام فیلدها و انواع آنها و همچنین متدها و انواع پاسخ آنها را مشاهده کنید.
نمودار همچنین روابط بین مدلها، از جمله تعدد آنها را نشان میدهد. تعدد مدل ها، اعدادی بر روی نمودار هستند که نشاندهنده تعداد (حداکثر و حداقل) هر مدل هستند که ممکن است در رابطه حاضر باشد. برای مثال، خط اتصال بین Box ها نشان میدهد که کتاب و یک ژانر به یکدیگر مرتبط هستند. اعداد نزدیک به مدل ژانر نشان میدهند که یک کتاب باید یک یا چند ژانر داشته باشد (هر تعداد که بخواهید)، در حالی که اعداد طرف دیگر خط که در کنار مدل کتاب قرار دارند، نشان میدهند که یک ژانر میتواند صفر یا چندین کتاب مرتبط داشته باشد.
نکته:
بخش بعدی الفبا ابتدایی برای چگونه تعریف شدن مدلها و همینطور مورد استفاده قرار دادن آنها را ارائه می دهد. همانطور که مطالعه میکنید، در نظر بگیرید که ما چگونه هر یک از مدلهای موجود در نمودار بالا را خواهیم ساخت.
آموزش الفبای مدل در Django
این بخش خلاصهای از نحوه تعریف یک مدل و برخی از فیلدهای مهم و آرگومان های فیلد را شرح میدهد.
تعریف مدل
مدلها معمولا در فایل models.py برنامه تعریف میشوند. آنها به عنوان زیرکلاس¬های django.db.models.Model اجرا می شوند و میتوانند فیلدها، متدها و metadata را شامل شوند. تکه کد زیر یک مدل "نمونه" به نام MyModelName را نشان میدهد:
from django.db import models
class MyModelName(models.Model):
"""A typical class defining a model, derived from the Model class."""
# Fields
my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')
...
# Metadata
class Meta:
ordering = ['-my_field_name']
# Methods
def get_absolute_url(self):
"""Returns the url to access a particular instance of MyModelName."""
return reverse('model-detail-view', args=[str(self.id)])
def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.my_field_name
در بخشهای زیر هر یک از ویژگیهای درون مدل را با جزئیات بررسی خواهیم کرد :
آموزش فیلدها در Django
یک مدل میتواند تعداد دلخواهی فیلد از هر نوعی داشته باشد، هر یک از این فیلدها یک ستون از دادهها را نشان میدهند که میخواهیم در یکی از جداول پایگاه داده ذخیره کنیم. هر رکورد پایگاهداده (سطر) شامل یک مقدار از هر فیلد خواهد بود. بیایید نگاهی به مثال زیر بیندازیم:
my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')
مثال بالا یک فیلد تکی به نام "my_field_name" از نوع models.CharField دارد - که به این معنی است که این فیلد حاوی رشتههایی از حروف و اعداد خواهد بود. انواع فیلد با استفاده از کلاسهای خاص اختصاص داده میشوند، که نوع رکورد مورد استفاده برای ذخیره دادهها در پایگاهداده، همراه با معیارهای اعتبار سنجی برای استفاده را تعیین میکنند، زمانی که مقادیر از قالب HTML دریافت میشوند (یعنی چیزی که یک مقدار معتبر است). انواع فیلد نیز میتوانند آرگومان هایی داشته باشند که در ادامه مشخص کنند فیلد چگونه ذخیره شده یا میتواند مورد استفاده قرار گیرد. در این مورد ما دو آرگومان خود را شرح میدهیم.
max_length=20 - بیان می کند که بیشترین طول یک مقدار در این فیلد ۲۰ کاراکتر است.
help_text='Enter field documentation' - یک برچسب متنی را برای نمایش دادن به کاربران ارائه میکند تا کاربران بدانند چه مقداری را باید فراهم کنند زمانی که این مقدار قرار است توسط یک کاربر از طریق فرم HTML وارد شود.
فیلد نام برای مورد هدف قرار دادن در کوئری ها و تمپلت¬ها استفاده میشود. فیلدها همچنین دارای برچسب مشخص شده به عنوان آرگومان (verbose_name) هستند، که مقدار پیشفرض آن None است و به معنای جایگزین کردن هر زیرمقداری در فیلد نام با یک فاصله است (برای مثال my_field_name دارای برچسب پیشفرض my field name خواهد بود). توجه داشته باشید که وقتی برچسب به عنوان برچسب فرم از طریق چارچوب Django استفاده میشود، اولین حرف برچسب بزرگ نوشته می شود (برای مثال my_field_name، برچسب My field name خواهد داشت).
ترتیبی که فیلدها ارائه می¬شوند بر ترتیب پیش¬فرض آنها تاثیر خواهد گذاشت، اگر مدل در یک فرم رندر شود (به عنوان مثال در سایت Admin)، هر چند که این امر ممکن است نادیده گرفته شود.
آرگومان های رایج فیلدها در Django
آرگومان های رایج زیر را می توان به هنگام ارائه انواع مختلف فیلدها به کار برد:
help_text:
یک برچسب متنی برای فرمهای HTML ارائه می کند (به عنوان مثال در سایت Admin)، همانطور که در بالا توضیح داده شد.
verbose_name:
یک نام قابل خواندن برای انسان برای فیلدی که در برچسب فیلدها بکار رفته است. اگر مشخص نشده باشد، Django نام پیش فرض را با نام فیلد جایگزین میکند.
default:
مقدار پیش فرض برای فیلد. این میتواند یک مقدار یا یک آبجکت قابل فراخوانی باشد، که در آن هر بار که یک رکورد جدید ایجاد شود، آن آبجکت فراخوانده می شود
null:
اگر True باشد، Django مقادیر خالی را به عنوان NULL در پایگاه داده برای فیلدهایی که مناسب باشد ذخیره میکند (یک CharField به جای یک رشته خالی ذخیره میشود). پیش فرض False است.
blank:
اگر True باشد، فیلد اجازه خالی بودن در فرم های شما را دارد. پیش فرض False است، که به این معنی است که اعتبار سنجی فرم Django شما را وادار به ورود یک مقدار خواهد کرد. این اغلب با null=True استفاده میشود، چون اگر بخواهید مقادیر خالی را مجاز کنید، پایگاهداده باید بتواند آنها را به طور مناسب نمایش دهد.
choices:
گروهی از انتخابها برای این فیلد. اگر داده ها به این شکل ارائه شوند، ویجت فرم مربوطه به جای فیلد متن استاندارد، یک جعبه انتخاب با گزینههای مورد نظر خواهد بود.
primary_key:
اگر True باشد، فیلد فعلی را به عنوان کلید پرایمری برای مدل تعیین میکند (کلید پرایمری یک ستون از پایگاهداده است که برای شناسایی منحصر به فرد تمام رکوردهای یک جدول خاص طراحی و مشخص شده است). اگر هیچ فیلدی به عنوان کلید پرایمری مشخص نشده باشد، آنگاه Django به طور خودکار یک فیلد را برای این منظور اضافه خواهد کرد.
انواع رایج فیلدها
در زیر برخی از انواع پرکاربرد مورد استفاده از انواع فیلدها آمده است.
CharField:
برای تعریف رشتههای کوتاه-تا-متوسط به کار می رود. شما باید max_lengh داده های ذخیرهشده را مشخص کنید.
TextField:
برای رشتههای بزرگ با طول دلخواه استفاده میشود. شما میتوانید max_length را برای فیلد مشخص کنید، اما این تنها زمانی استفاده میشود که فیلد در فرم ها نمایش داده شود (در سطح پایگاهداده اجرا نمی شود).
IntegerField:
یک فیلد برای ذخیرهسازی مقادیر عددی (عدد کامل)، و برای معتبر کردن مقادیر وارد شده به صورت اعداد صحیح است.
DateTimeField و DateField:
برای ذخیرهسازی/نمایش تاریخ و اطلاعات تاریخ/زمان (در پایتون، آبجکت¬های datetime.date و datetime.date، به ترتیب) استفاده می شوند. این فیلدها همچنین میتوانند پارامترهای (متقابلا انحصاری) را معرفی کنند auto_now=True (برای تنظیم فیلد به تاریخ فعلی برای هر بار که مدل ذخیره میشود)، auto_now_add (برای تنظیم تاریخ تنها زمانی که مدل اولین بار ایجاد می شود)، و default (برای تنظیم تاریخ پیش فرض که میتواند توسط کاربر نادیده گرفته شود).
EmailField
برای ذخیره و اعتبار سنجی آدرسهای ایمیل استفاده میشود.
FileField و ImageField
به ترتیب برای بارگذاری فایل و تصاویر به کار میروند (ImageField اعتبار اضافی را ایجاد میکند تا تائید کند فایل بارگذاری شده یک تصویر است). این ها باید پارامترهایی داشته باشند تا مشخص کنند فایلهای بارگذاری شده چگونه و کجا ذخیره میشوند.
AutoField
یک نوع خاص از IntegerField است که به طور خودکار افزایش مییابد. اگر خودتان کلید پرایمری را مشخص نکنید، یک نوع از این کلید به طور خودکار به مدل شما اضافه میشود.
ForeignKey
برای مشخص کردن رابطه یک به چند با مدل دیگر پایگاهداده استفاده میشود (به عنوان مثال یک خودرو دارای یک کارخانه سازنده است، اما تولید کننده میتواند چندین خودرو تولید کند). "یک" طرفی از رابطه است که حاوی "کلید" می باشد (مدلهای حاوی یک "کلید خارجی" به آن "کلید" اشاره دارند، در "بسیاری" از طرف های چنین رابطه ای حضور دارند).
ManyToManyField
برای مشخص کردن رابطه چند به چند استفاده میشود (به عنوان مثال یک کتاب میتواند چندین ژانر داشته باشد، و هر ژانر میتواند شامل چندین کتاب باشد). در برنامه کتابخانه، ما از این شباهت ها با ForeignKeys استفاده خواهیم کرد، اما می¬توان آنها را به روشهای پیچیدهتری برای توصیف روابط بین گروهها استفاده کرد. پارامتری به نام on_delete وجود دارد تا مشخص کنند که در زمان حذف رکورد، چه اتفاقی میافتد (به عنوان مثال مقدار models.SET_NULL مقدار را به NULL تنظیم میکند).
انواع دیگر فیلد نیز وجود دارد، از جمله فیلدهایی برای انواع مختلف اعداد (اعداد صحیح بزرگ، اعداد صحیح کوچک، شناور)، بولین ها، URL ها، اسلاگ ها (نامک)، آیدی های یگانه و اطلاعات دیگر "وابسته به زمان" (مدت، زمان و غیره).
آموزش Metadata در Django
شما میتوانید Metadata سطح مدل را برای مدل خود و با اجرای class Meta، به صورت زیر تعیین کنید.
class Meta:
ordering = ['-my_field_name']
زمانی که برای نوع مدل، کوئری می نویسید، یکی از مهمترین ویژگیهای Metadata، کنترل نظم پیش فرض رکوردهای بازگشتی است. همانطور که در بالا نشانداده شدهاست، شما این کار را با مشخص کردن آرایش متناظر در لیستی از نامهای فیلد در خصوصیت ordering انجام میدهید. این ترتیب به نوع فیلد (کاراکترهای فیلد براساس حروف الفبایی مرتب می-شوند، در حالی که فیلدهای تاریخ به ترتیب زمانی مرتب می شوند) بستگی دارد. همانطور که در بالا نشان داده شد، میتوانید نام فیلد را با زدن علامت منفی (-) به صورت معکوس مرتب سازی کنید.
به عنوان مثال، اگر بخواهیم کتابهایی را به این صورت به طور پیش فرض حذف کنیم:
ordering = ['title', '-pubdate']
کتاب ها با توجه به عنوان، از A – Z، و سپس با تاریخ انتشار داخل هر عنوان، از جدیدترین تا قدیمی ترین، مرتب میشوند.
یک خصوصیت رایج دیگر، verbose_name است که همان اسم کامل برای کلاس به صورت مفرد و جمع را نشان می دهد:
verbose_name = 'BetterName'
سایر خصوصیات مفید به شما این امکان را میدهند که "مجوزهای دسترسی" جدید برای این مدل ایجاد کنید (مجوزهای پیش فرض به طور خودکار بکار گرفته می شوند)، ترتیب را بر اساس فیلد دیگری تنظیم کنید، و یا اعلام کنید که کلاس "انتزاعی" است (یک کلاس پایه که شما نمیتوانید رکوردی برای آن ایجاد کنید، و مشتق شده تا مدلهای دیگری را ایجاد کند).
بسیاری از گزینههای دیگر matadata کنترل می¬کنند که کدام پایگاهداده باید برای مدل مورد استفاده قرار گیرد تا بتوان دادهها را ذخیره کرد (اینها واقعا تنها در صورتی مفید هستند که شما بخواهید یک مدل را به یک پایگاهداده موجود آدرس دهی کنید).
آموزش متدها در Django
یک مدل همچنین می تواند چند متد داشته باشد.
در حالت حداقلی، هر مدل باید متد استاندارد کلاس پایتون __str__() را تعریف کند تا بتواند برای هر آبجکت، یک رشته قابل خواندن برگرداند. این رشته برای نشان دادن رکوردهای واحد در سایت Admin (و هر جای دیگری که شما نیاز به ارجاع به یک نمونه مدل داشته باشید) استفاده می شود. غالباً این دستور، فیلد عنوان یا نام را از مدل بازمی گرداند.
def __str__(self):
return self.field_name
متد متداول دیگری که در مدل های Django گنجانده شده، متد get_absolute_url() است که یک URL را برای نمایش رکورد واحد مدل در وب سایت بازمی گرداند (اگر این متد را تعریف کنید، Django به طور خودکار دکمه "نمایش در سایت" را به صفحه ویرایش رکورد مدل در سایت Admin اضافه می کند). یک الگوی معمولی برای get_absolute_url() در زیر نشان داده شده است.
با فرض اینکه شما از URL هایی مانند /myapplication/mymodelname/2 برای نمایش رکوردهای واحد مدل خود استفاده خواهید¬کرد (جایی که "2" id یک رکورد خاص است)، شما باید یک نقشه¬یاب URL برای انتقال پاسخ و id به "وبو جزئیات مدل" ایجاد کنید (که کار مورد نیاز برای نمایش رکورد را انجام می دهد). تابع reverse() در بالا قادر است نقشه-یاب URL شما را "معکوس" کند (در مورد بالا نام آن "model-detail-view" است) تا یک URL با قالب مناسب ایجاد کند.
مطمئناً برای درست اجرا شدن این مورد، شما هنوز باید نقشه یابی URL، ویو و تمپلت آماده را بنویسید!
همچنین می توانید هر متد دیگری که دوست دارید را تعریف کرده و از طریق کد یا تمپلت های آماده خود آنها را فراخوانی کنید (به شرطی که هیچ پارامتری نگیرند).
مدیریت مدل
هنگامی که کلاس های مدل خود را تعریف کردید، می توانید از آنها برای ایجاد، به روزرسانی یا حذف رکوردها و همینطور اجرای کوئری برای بدست آوردن همه رکوردها یا زیرمجموعه های خاصی از رکوردها استفاده کنید. در ادامه این آموزش به شما خواهیم گفت چطور این کار را در زمان تعریف ویوهای خود انجام دهید، اما در اینجا یک خلاصه مختصر آورده شده است.
ایجاد و اصلاح رکوردها در Django
برای ایجاد یک رکورد می توانید نمونه ای از مدل را تعریف کنید و سپس save() را فراخوانی کنید.
# Create a new record using the model's constructor.
record = MyModelName(my_field_name="Instance #1")
# Save the object into the database.
record.save()
اگر فیلدی را به عنوان primary_key انتخاب نکرده اید، کلیدی به صورت خودکار و با نام فیلد id به رکورد جدید داده می شود. می توانید پس از ذخیره رکورد فوق، آن را کوئری نویسی کنید و مقدار آن می تواند 1 باشد.
با استفاده از سینتکس نقطه می توانید به فیلدهای موجود در این رکورد جدید دسترسی پیدا کرده و مقادیر را تغییر دهید. برای ذخیره مقادیر تغییر یافته در پایگاه داده، باید save() را فراخوانی کنید.
# Access model field values using Python attributes.
print(record.id) # should return 1 for the first record.
print(record.my_field_name) # should print 'Instance #1'
# Change record by modifying the fields, then calling save().
record.my_field_name = "New Instance Name"
record.save()
جستجوی رکوردها در Django
با استفاده از خصوصیت objects در مدل (ارائه شده توسط کلاس پایه) می توانید رکوردهایی متناسب با معیارهای خاص را جستجو کنید.
: توضیح چگونگی جستجوی رکوردها با استفاده از مدل "انتزاعی" و نام فیلدها می تواند کمی گیج کننده باشد. در بحث زیر ما به یک مدل book با فیلدهای genre و title مراجعه خواهیم کرد، که ژانر نیز یک مدل با فیلد واحد name است.
می توانیم تمام رکوردهای مربوط به یک مدل را با استفاده از objects.all() به صورت QuerySet بدست آوریم. QuerySet یک آبجکت قابل تکرار است، به این معنی که شامل تعدادی آبجکت است که می توانیم آنها را تکرار کنیم.
all_books = Book.objects.all()
متد filter() در Django به ما این امکان را می¬دهد که QuerySet برگردانده شده را برای مطابقت با فیلد متنی یا عددی مشخص با معیارهای خاص فیلتر کنیم. به عنوان مثال، از این متد می توان برای فیلتر کردن کتابهایی که در عنوان آنها عبارت "وحشی" وجود دارد و سپس شمارش آنها، بصورت زیر استفاده کرد.
wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = wild_books.count()
فیلدهایی که باید مطابقت داده شوند و همینطور نوع مطابقت آنها، در نام پارامتر فیلتر با استفاده از قالب field_name__match_type تعریف می شود (به دو زیرخط میان title و contains در بالا توجه کنید). در بالا ما title را با یک تطابق حساس به حروف بزرگ فیلتر می¬کنیم. انواع مختلفی از تطابق وجود دارد که می توانید انجام دهید: icontains (عدم حساسیت به حروف بزرگ)، iexact (تطابق دقیق حروف کوچک)، exact (تطابق دقیق حساس به حروف بزرگ) وin ، gt (بزرگتر از)، startwith و غیره. لیست کامل اینجاست.
در برخی موارد، باید فیلدی را فیلتر کنید که رابطه یک به چند با یک مدل دیگر را تعریف می کند (به عنوان مثال یک ForeignKey). در این حالت، شما میتوانید "فهرست" فیلدها را در یک مدل مرتبط با زیرخط های دوتایی اضافه کنید. بنابراین برای مثال، همانطور که در زیر نشان داده شده است، جهت فیلتر کردن کتابها با الگوی ژانر خاص، باید name را از طریق فیلد genre فهرست کنید:
# Will match on: Fiction, Science fiction, non-fiction etc.
books_containing_genre = Book.objects.filter(genre__name__icontains='fiction')
شما میتوانید از زیرخط ها (__) برای هدایت کردن هر تعداد از روابط (ForeignKey/ManyToManyField) که مورد نظر شماست، استفاده کنید. برای مثال، یک book که انواع مختلفی دارد، با استفاده از رابطه "cover" تعریف می شود که ممکن است دارای یک نام باشد:
type__cover__name__exact='hard'
کارهای بیشتری میتوانید با کوئری انجام دهید، از جمله جستجوهای وارونه از مدلهای مرتبط، فیلترهای زنجیری، بازگشت مجموعه کوچکتری از مقادیر و غیره.
تعریف مدلهای LocalLibrary
در این بخش ما شروع به تعریف مدلهای کتابخانه خواهیم کرد. models.py را باز کنید (در /locallibrary/catalog/). boilerplate در بالای صفحه ماژول مدلها را وارد میکند که شامل کلاس مدل پایه models.model است و مدل ما از آن ارث بری می کند.
from django.db import models
# Create your models here.
مدل ژانر
کد مدل Genre در زیر را کپی کرده و آن را به انتهای فایل models.py خود بچسبانید. این مدل برای ذخیره اطلاعات درباره دسته بندی کتاب به کار میرود - به عنوان مثال، ژانر آن تخیلی است یا غیر تخیلی، داستان عاشقانه یا تاریخ نظامی، و غیره. همانطور که در بالا اشاره شد، ما Genre را به عنوان یک مدل، و نه متن آزاد یا لیست انتخابی، ایجاد کردهایم تا مقادیر ممکن را بتوان از طریق پایگاهداده اداره کرد و نه به صورت کدنویسی ساخت.
class Genre(models.Model):
"""Model representing a book genre."""
name = models.CharField(max_length=200, help_text='Enter a book genre (e.g. Science Fiction)')
def __str__(self):
"""String for representing the Model object."""
return self.name
این مدل دارای یک فیلد واحد CharField (name) است، که برای توصیف ژانر مورد استفاده قرار میگیرد (این به ۲۰۰ کاراکتر محدود شده و دارای help_text است. در پایان مدل، ما یک متد __str__() را اعلام میکنیم، که نام ژانر تعریفشده توسط یک رکورد مشخص را باز می گرداند. از آنجا که هیچ نام کاملی تعریف نشده ، فیلد در فرم ها Name نامیده میشود.
مدل کتاب
مدل Book در زیر را کپی کرده و دوباره آن را به انتهای فایل بچسبانید. مدل Book تمامی اطلاعات مربوط به یک کتاب در دسترس را به طور کلی ارائه میدهد، اما نه یک "نمونه" خاص فیزیکی یا "کپی" برای امانت گرفتن. مدل از یک CharField برای نشان دادن title کتاب و isbn استفاده میکند. برای isbn، توجه داشته باشید که چگونه پارامتر بدون نام اول به صراحت برچسب را به نام "ISBN" تعیین میکند (در غیر این صورت پیشفرض "Isbn" است). ما همچنین پارامتر unique را به صورت true تنظیم کردیم تا اطمینان حاصل کنیم همه کتابها دارای ISBN منحصر به فرد هستند (پارامتر منحصر به فرد، مقدار فیلد را در سطح جهانی در جدول منحصر به فرد میسازد). از آنجا که این متن ممکن است بسیار طولانی باشد، این مدل از TextField برای summary استفاده میشود.
from django.urls import reverse # Used to generate URLs by reversing the URL patterns
class Book(models.Model):
"""Model representing a book (but not a specific copy of a book)."""
title = models.CharField(max_length=200)
# Foreign Key used because book can only have one author, but authors can have multiple books
# Author as a string rather than object because it hasn't been declared yet in the file
author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
summary = models.TextField(max_length=1000, help_text='Enter a brief description of the book')
isbn = models.CharField('ISBN', max_length=13, unique=True,
help_text='13 Character ISBN number')
# ManyToManyField used because genre can contain many books. Books can cover many genres.
# Genre class has already been defined so we can specify the object above.
genre = models.ManyToManyField(Genre, help_text='Select a genre for this book')
def __str__(self):
"""String for representing the Model object."""
return self.title
def get_absolute_url(self):
"""Returns the url to access a detail record for this book."""
return reverse('book-detail', args=[str(self.id)])
این ژانر یک ManyToManyField است، به طوری که یک کتاب میتواند چندین ژانر داشته باشد و یک ژانر می تواند به کتابهای زیادی مرتبط باشد. مولف به عنوان ForeignKey اعلام میشود، بنابراین هر کتاب تنها یک نویسنده دارد، اما مولف ممکن است کتابهای زیادی داشته باشد (در عمل یک کتاب ممکن است چندین نویسنده داشته باشد، اما در این مثال این مورد رعایت نشده است!)
در هر دو نوع فیلد، مدل کلاس مربوطه به عنوان اولین پارامتر بدون نام یا با استفاده از کلاس مدل یا یک رشته شامل نام مدل مربوطه اعلام میشود. اگر قبل از ارجاع به کلاس مربوطه، کلاس هنوز در این فایل تعریف نشده باشد، باید از نام مدل به عنوان یک رشته استفاده کنید! دیگر پارامترهای مورد علاقه در فیلد author، null=True است که به پایگاه داده اجازه میدهد اگر هیچ مولفی انتخاب نشود، یک مقدار Null را ذخیره کند، و اگر رکورد نویسنده مربوطه حذف شود، دستور on_delete=models.SET_NULL، مقدار فیلد نویسنده کتاب را به Null تنظیم میکند.
دستور on_delete=models.CASCADE به طور پیش فرض به این معنی است که اگر نویسنده حذف شد، این کتاب نیز باید حذف شود! در اینجا ما از SET_NULL استفاده میکنیم، اما میتوانیم از PROTECT یا RESTRICT برای جلوگیری از حذف نویسنده استفاده کنیم.
این مدل که __str__() را نیز تعریف می¬کند، از فیلد title کتاب برای نشان دادن رکورد Book استفاده میکند. متد نهایی، get_absolute_url() یک URL را باز میگرداند که می تواند برای دسترسی به یک رکورد دقیق برای این مدل استفاده شود (برای این کار ما باید یک نقشه یاب URL را تعریف کنیم که نام فایل book-detail را در اختیار دارد و ویو و تمپلت مرتبط را تعریف میکند).
مدل BookInstance
سپس، مدل BookInstance (نشاندادهشده در زیر) را زیر مدلهای دیگر کپی کنید. BookInstance یک کپی خاص از کتابی را نشان میدهد که ممکن است کسی قرض گرفته باشد، و اطلاعات زیر را شامل می شود : آیا کپی در دسترس است یا نه، در چه تاریخی بازگشت داده می شود، "imprint" یا جزئیات نسخه، و یک آیدی منحصر به فرد برای کتاب در کتابخانه را نیز در نظر می گیرد.
با برخی از فیلدها و متدها آشنا شدید. این مدل از موارد زیر استفاده میکند :
-
ForeignKey برای شناسایی کتاب مربوطه (هر کتاب میتواند کپیهای زیادی داشته باشد، اما یک کپی فقط میتواند مربوط به یک کتاب باشد). کلید، on_delete=models.RESTRICT را تعیین کرده تا اطمینان حاصل شود که نمیتوان Book را هنگام ارجاع توسط یک BookInstance، حذف کرد.
-
CharField برای نشان دادن نسخه (انتشار خاص) کتاب.
import uuid # Required for unique book instances
class BookInstance(models.Model):
"""Model representing a specific copy of a book (i.e. that can be borrowed from the library)."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular book across whole library')
book = models.ForeignKey('Book', on_delete=models.RESTRICT)
imprint = models.CharField(max_length=200)
due_back = models.DateField(null=True, blank=True)
LOAN_STATUS = (
('m', 'Maintenance'),
('o', 'On loan'),
('a', 'Available'),
('r', 'Reserved'),
)
status = models.CharField(
max_length=1,
choices=LOAN_STATUS,
blank=True,
default='m',
help_text='Book availability',
)
class Meta:
ordering = ['due_back']
def __str__(self):
"""String for representing the Model object."""
return f'{self.id} ({self.book.title})'
ما چند نوع جدید از فیلدها را معرفی می کنیم:
UUIDField
برای فیلد id استفاده شده که آن را به عنوان primary_key برای این مدل تنظیم میکند. این نوع فیلد یک مقدار منحصر به فرد جهانی را برای هر نمونه اختصاص میدهد (یکی برای هر کتابی که میتوانید در کتابخانه پیدا کنید).
DateField
برای due_back تاریخ استفاده می شود (تاریخی که انتظار میرود کتاب پس از قرض گرفتن یا نگهداری در دسترس قرار گیرد). این مقدار میتواند blank یا null باشد (برای زمان موجود بودن کتاب نیاز است). metadata¬های مدل زمانی که در پاسخ به کوئری بازگشت داده می شوند، (Class Meta) از این فیلد برای ترتیب رکوردها استفاده میکنند.
status
یک CharField است که فهرستی از گزینه های قابل انتخاب را تعریف میکند. همانطور که مشاهده می کنید، ما یک Tuples متشکل از چندین زوج با مقدار-کلیدی تعریف میکنیم و آن را به آرگومان گزینه های قابل انتخاب انتقال می دهیم. مقدار در یک جفت کلید/مقدار، مقدار نمایشی است که یک کاربر میتواند انتخاب کند، در حالی که کلیدها مقادیری هستند که در صورت انتخاب یک گزینه، ذخیره میشوند. از آنجا که کتابها، قبل از این که در قفسهها جا داده شوند، به صورت عدم دسترس ثبت می شوند، یک مقدار پیش فرض "m" (نگهداری) تنظیم کردهایم.
متد __str__() آبجکت BookInstance را با استفاده از ترکیبی از شناسه منحصر به فرد آن و عنوان کتاب مربوطه نشان میدهد.
با شروع با پایتون ۳.۶، میتوانید از سینتکس درج رشتهای (به نام f-strings هم شناخته می شود) استفاده کنید:
f'{self.id} ({self.book.title})'
در نسخههای قدیمیتر این آموزش، ما از یک سینتکس رشتهای قالب بندی شده استفاده کردیم، که یک روش معتبر برای قالب بندی رشته ها در پایتون است (به عنوان مثال
'{0} ({1})'.format(self.id,self.book.title))
مدل نویسنده
مدل Author را (که در پایین نشانداده شده) در زیر کد موجود در models.py کپی کنید.
class Author(models.Model):
"""Model representing an author."""
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)
class Meta:
ordering = ['last_name', 'first_name']
def get_absolute_url(self):
"""Returns the url to access a particular author instance."""
return reverse('author-detail', args=[str(self.id)])
def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'
حالا باید با همه فیلدها/متدها آشنا شده باشید. این مدل، یک نویسنده را با نام، نامخانوادگی، و تاریخ تولد و وفات (هر دو اختیاری) تعریف میکند. این متد به طور پیش فرض مشخص میکند که __str__() نام را به ترتیب نام خانوادگی و نام بازمیگرداند. متد get_absolute_url() نقشه¬یابی URL را برای author_detail معکوس میکند تا URL را برای نمایش یک نویسنده به دست آورد.
راهاندازی مجدد انتقال پایگاهداده
همه مدلهای شما حالا ساخته شدهاند. حالا مهاجرت پایگاه داده خود را دوباره اجرا کرده تا آنها را به پایگاهداده خود اضافه کنید.
python3 manage.py makemigrations
python3 manage.py migrate
مدل زبانی - چالش
تصور کنید که یک حامی محلی، تعدادی کتابهای جدید که به زبان دیگری (مثلا فارسی) هستند را به شما اهدا میکند. چالش این است که توضیح دهید چگونه اینها به بهترین شکل در وب سایت کتابخانه ما نمایش داده میشوند و سپس آنها را به مدلها اضافه کنید.
برخی چیزهایی که باید در نظر بگیرید:
آیا "زبان" باید به یک Book، BookInstance، یا چند آبجکت دیگر مرتبط باشد؟
آیا زبانهای مختلف باید با استفاده از مدل، یک فیلد متنی آزاد، یا یک فهرست انتخاب کدگذاری شده نمایش داده شوند؟
فراموش نکنید که بعد از تغییر دادن مدل خود، باز باید انتقال پایگاه داده را دوباره اجرا کنید تا تغییرات اضافه شوند.
python3 manage.py makemigrations
python3 manage.py migrate
خلاصه
در این مقاله ما یاد گرفتیم که چگونه مدلها تعریف میشوند و سپس از این اطلاعات برای طراحی و اجرای مدلهای مناسب برای وب سایت LocalLibrary استفاده کردیم.
در این مرحله، ما بطور خلاصه از ساخت سایت منحرف شده و سایت Django Adminstration را بررسی میکنیم. این سایت به ما اجازه میدهد تا برخی از دادهها را به کتابخانه اضافه کنیم، و پس از آن با استفاده از ویو و تمپلت های آماده خود (که هنوز ایجاد نکرده ایم) به نمایش درآوریم.