مقدمه
در این آموزش، مدلهای جنگو را ایجاد میکنیم که فیلدها و رفتارهای دادههای برنامه بلاگ را که ذخیره خواهیم کرد، تعریف میکنند. این مدلها دادههای برنامه جنگو شما را به پایگاه داده نگاشت میکنند. این همان چیزی است که جنگو برای تولید جداول پایگاه داده از طریق API نگاشت رابطهای شی (ORM) که به آن «مدلها» گفته میشود، استفاده میکند.
پیش نیازها
این آموزش بخشی از سری توسعه جنگو است و ادامه آن مجموعه است.
اگر این مجموعه را دنبال نکرده اید، فرضیات زیر را مطرح می کنیم:
- شما نسخه 4 یا بالاتر جنگو را نصب کرده اید.
- شما برنامه جنگو خود را به یک پایگاه داده متصل کرده اید.
- شما با یک سیستم عامل مبتنی بر یونیکس کار می کنید، ترجیحاً یک سرور ابری اوبونتو 22.04 زیرا این سیستمی است که ما روی آن آزمایش کرده ایم.
از آنجایی که این آموزش عمدتاً به مدلهای جنگو میپردازد، حتی اگر تنظیمات متفاوتی دارید، ممکن است بتوانید آن را دنبال کنید.
مرحله 1 – برنامه جنگو را ایجاد کنید
برای سازگاری با فلسفه ماژولار بودن جنگو، ما یک برنامه جنگو را در پروژه خود ایجاد می کنیم که حاوی تمام فایل های لازم برای ایجاد وب سایت وبلاگ است.
هر زمان که شروع به انجام کار در پایتون و جنگو می کنیم، باید محیط مجازی پایتون خود را فعال کرده و به دایرکتوری اصلی برنامه خود منتقل کنیم. اگر همراه با سریال دنبال کردید، می توانید با تایپ کردن موارد زیر به این امر برسید.
cd ~/my_blog_app
. env/bin/activate
cd blogr code... */
از آنجا، بیایید این دستور را اجرا کنیم:
python manage.py startapp blogsite
این برنامه ما را به همراه یک فهرست سایت وبلاگ ایجاد می کند.
در این مرحله از سری آموزش، ساختار دایرکتوری زیر را برای پروژه خود خواهید داشت:
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── settings.cpython-38.pyc
│ │ ├── urls.cpython-38.pyc
│ │ └── wsgi.cpython-38.pyc
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
فایلی که برای این آموزش روی آن تمرکز خواهیم کرد، فایل models.py خواهد بود که در دایرکتوری وبلاگ سایت قرار دارد.
مرحله 2 – مدل پست ها را اضافه کنید
ابتدا باید فایل models.py را باز کرده و ویرایش کنیم تا حاوی کد تولید یک مدل Post باشد. یک مدل Post شامل فیلدهای پایگاه داده زیر است:
- TITLE – عنوان پست وبلاگ.
- Slug – جایی که URL های معتبر برای صفحات وب ذخیره و تولید می شوند.
- CONTENT – محتوای متنی پست وبلاگ.
- create_on – تاریخی که پست در آن ایجاد شد.
- AUTHOR – شخصی که پست را نوشته است.
اکنون به فهرستی که فایل models.py در آن قرار دارد بروید.
cd ~/my_blog_app/blog/blogsite
از دستور cat برای نمایش محتویات فایل در ترمینال خود استفاده کنید.
cat models.py
فایل باید کد زیر را داشته باشد که مدلها را وارد میکند، همراه با یک نظر که توضیح میدهد چه چیزی در این فایل models.py قرار میگیرد.
from django.db import models
# Create your models here.
با استفاده از ویرایشگر متن مورد علاقه خود، کد زیر را به فایل models.py اضافه کنید. ما از نانو به عنوان ویرایشگر متن خود استفاده خواهیم کرد، اما شما می توانید از هر چیزی که ترجیح می دهید استفاده کنید.
nano models.py
در این فایل، کد وارد کردن API مدلها قبلاً اضافه شده است، میتوانیم ادامه دهیم و نظر زیر را حذف کنیم. سپس slugify را برای تولید اسلاگ از رشتهها، کاربر جنگو را برای احراز هویت، و معکوس از django.urls وارد میکنیم تا انعطافپذیری بیشتری در ایجاد URL به ما بدهیم.
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
سپس، متد کلاس را با فیلدهای پایگاه داده زیر، عنوان، اسلاگ، محتوا، create_on و نویسنده، روی کلاس مدلی که Post می نامیم اضافه کنید. اینها را در زیر عبارات واردات خود اضافه کنید.
...
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
در مرحله بعد، عملکردی برای تولید URL و تابع ذخیره پست اضافه می کنیم. این بسیار مهم است، زیرا این یک پیوند منحصر به فرد برای مطابقت با پست منحصر به فرد ما ایجاد می کند.
...
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
اکنون باید به مدل بگوییم که پستها چگونه باید مرتب شوند و در صفحه وب نمایش داده شوند. منطق این به یک کلاس متای داخلی تو در تو اضافه خواهد شد. کلاس متا به طور کلی شامل منطق مدل مهم دیگری است که به تعریف فیلد پایگاه داده مربوط نمی شود.
...
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
در نهایت مدل Comment را به این فایل اضافه می کنیم. این شامل اضافه کردن کلاس دیگری به نام Comment با models.Models در امضای آن و تعریف فیلدهای پایگاه داده زیر است:
- NAME – نام شخصی که نظر را ارسال می کند.
- EMAIL – آدرس ایمیل شخصی که نظر را ارسال می کند.
- TEXT – متن خود نظر.
- POST – پستی که با آن نظر داده شده است.
- create_on – زمانی که نظر ایجاد شد.
...
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
در این مرحله models.py کامل خواهد شد. مطمئن شوید که فایل models.py شما با موارد زیر مطابقت دارد:
from django.db import models
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=255)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
author = models.TextField()
def get_absolute_url(self):
return reverse('blog_post_detail', args=[self.slug])
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
class Meta:
ordering = ['created_on']
def __unicode__(self):
return self.title
class Comment(models.Model):
name = models.CharField(max_length=42)
email = models.EmailField(max_length=75)
website = models.URLField(max_length=200, null=True, blank=True)
content = models.TextField()
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
حتما فایل را ذخیره و ببندید. اگر از nano استفاده می کنید، می توانید این کار را با تایپ CTRL و X، سپس Y و سپس ENTER انجام دهید.
با راه اندازی فایل models.py، می توانیم فایل settings.py خود را به روز کنیم.
مرحله 3 – تنظیمات را به روز کنید
اکنون که مدلهایی را به برنامه خود اضافه کردهایم، باید پروژه خود را از وجود برنامه وبلاگسایت که به تازگی اضافه کردهایم مطلع کنیم. ما این کار را با افزودن آن به بخش INSTALLED_APPS در settings.py انجام می دهیم.
به دایرکتوری که settings.py شما در آن زندگی می کند بروید.
cd ~/my_blog_app/blog/blog
از اینجا، فایل settings.py خود را به عنوان مثال با nano باز کنید.
nano settings.py
همانطور که در زیر نشان داده شده است، با باز کردن فایل، برنامه وبلاگ سایت خود را به بخش INSTALLED_APPS فایل اضافه کنید.
# Application definition
INSTALLED_APPS = [
'blogsite',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
با اضافه شدن برنامه وبلاگ سایت، می توانید فایل را ذخیره کرده و از آن خارج شوید.
در این مرحله، ما آماده حرکت برای اعمال این تغییرات هستیم.
مرحله 4 – مهاجرت انجام دهید
با اضافه شدن مدلهای Post و Comment، گام بعدی اعمال این تغییرات است تا طرح پایگاه داده MySQL ما آنها را بشناسد و جداول لازم را ایجاد کند.
ابتدا، ما باید تغییرات مدل خود را با استفاده از دستور makemigrations در فایلهای مهاجرت جداگانه بسته بندی کنیم. این فایل ها شبیه به commit ها در یک سیستم کنترل نسخه مانند Git هستند.
اکنون، اگر به ~/my_blog_app/blog/blogsite/migrations بروید و ls را اجرا کنید، متوجه خواهید شد که فقط یک فایل __init__.py وجود دارد. هنگامی که ما مهاجرت ها را اضافه کنیم، این تغییر می کند.
با استفاده از cd به فهرست وبلاگ تغییر دهید، مانند:
cd ~/my_blog_app/blog
سپس دستور makemigrations را در manager.py اجرا کنید.
python manage.py makemigrations
سپس باید خروجی زیر را در پنجره ترمینال خود دریافت کنید:
Output
Migrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Post
- Create model Comment
به یاد دارید، زمانی که به /~/my_blog_app/blog/blogsite/migrations رفتیم و فقط فایل __init__.py را داشت؟ اگر اکنون به آن فهرست برگردیم، متوجه میشویم که دو مورد اضافه شده است: __pycache__ و 0001_initial.py. فایل 0001_initial.py به طور خودکار هنگام اجرای makemigrations ایجاد شد. هر بار که makemigrations را اجرا می کنید یک فایل مشابه ایجاد می شود.
اگر میخواهید محتوای فایل را بخوانید، کمتر 0001_initial.py را از دایرکتوری که در آن قرار دارد اجرا کنید.
اکنون به ~/my_blog_app/blog بروید:
cd ~/my_blog_app/blog
از آنجایی که ما یک فایل مهاجرت ساختهایم، باید تغییراتی را که این فایلها توصیف میکنند با استفاده از دستور migre در پایگاه داده اعمال کنیم. اما ابتدا بیایید با استفاده از دستور showmigrations بررسی کنیم که کدام مهاجرت در حال حاضر وجود دارد.
python manage.py showmigrations
Output
admin
[X] 0001_initial
[X] 0002_logentry_remove_auto_add
[X] 0003_logentry_add_action_flag_choices
auth
[X] 0001_initial
[X] 0002_alter_permission_name_max_length
[X] 0003_alter_user_email_max_length
[X] 0004_alter_user_username_opts
[X] 0005_alter_user_last_login_null
[X] 0006_require_contenttypes_0002
[X] 0007_alter_validators_add_error_messages
[X] 0008_alter_user_username_max_length
[X] 0009_alter_user_last_name_max_length
[X] 0010_alter_group_name_max_length
[X] 0011_update_proxy_permissions
blogsite
[ ] 0001_initial
contenttypes
[X] 0001_initial
[X] 0002_remove_content_type_name
sessions
[X] 0001_initial
متوجه میشوید که همه مهاجرتها بررسی میشوند، به جز موردی که برای 0001_initial که با مدلهای Post و Comment ایجاد کردیم.
حالا بیایید با استفاده از دستور زیر بررسی کنیم که کدام عبارات SQL پس از انجام مهاجرت ها اجرا می شوند. مهاجرت و عنوان migration را به عنوان یک آرگومان می گیرد:
python manage.py sqlmigrate blogsite 0001_initial
در زیر نشان داده شده است که پرس و جو واقعی SQL در پشت صحنه انجام می شود.
Output
--
-- Create model Post
--
CREATE TABLE `blogsite_post` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(255) NOT NULL, `slug` varchar(255) NOT NULL UNIQUE, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `author` longtext NOT NULL);
--
-- Create model Comment
--
CREATE TABLE `blogsite_comment` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `name` varchar(42) NOT NULL, `email` varchar(75) NOT NULL, `website` varchar(200) NULL, `content` longtext NOT NULL, `created_on` datetime(6) NOT NULL, `post_id` integer NOT NULL);
ALTER TABLE `blogsite_comment` ADD CONSTRAINT `blogsite_comment_post_id_de248bfe_fk_blogsite_post_id` FOREIGN KEY (`post_id`) REFERENCES `blogsite_post` (`id`);
بیایید اکنون مهاجرت ها را انجام دهیم تا در پایگاه داده MySQL ما اعمال شوند.
python manage.py migrate
خروجی زیر را دریافت خواهیم کرد:
Output
Operations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying blogsite.0001_initial... OK
اکنون مهاجرت های خود را با موفقیت اعمال کرده اید.
مهم است که به خاطر داشته باشید که همانطور که در مستندات جنگو بیان شده است، سه اخطار برای مهاجرت جنگو با MySQL به عنوان باطن وجود دارد.
- عدم پشتیبانی از تراکنش های پیرامون عملیات تغییر طرحواره. به عبارت دیگر، اگر یک مهاجرت با موفقیت اعمال نشد، باید تغییراتی را که ایجاد کردهاید به صورت دستی انتخاب کنید تا مهاجرت دیگری را انجام دهید. قبل از ایجاد هرگونه تغییر در مهاجرت ناموفق، امکان بازگشت به نقطه قبلی وجود ندارد.
- برای اکثر عملیات تغییر طرحواره، MySQL جداول را به طور کامل بازنویسی می کند. در بدترین حالت، پیچیدگی زمانی متناسب با تعداد ردیفهای جدول برای افزودن یا حذف ستونها خواهد بود. با توجه به مستندات جنگو، این سرعت می تواند به کندی یک دقیقه در هر میلیون ردیف باشد.
- در MySQL، محدودیت های کوچکی در طول نام برای ستون ها، جداول و شاخص ها وجود دارد. همچنین محدودیتی در اندازه ترکیبی همه ستون ها و جلدهای فهرست وجود دارد. در حالی که برخی از پشتیبانهای دیگر میتوانند محدودیتهای بالاتر ایجاد شده در جنگو را پشتیبانی کنند، همان شاخصها با وجود یک Backend MySQL ایجاد نمیشوند.
برای هر پایگاه داده ای که برای استفاده با جنگو در نظر می گیرید، حتماً مزایا و معایب هر کدام را بسنجید.
مرحله 5 – طرحواره پایگاه داده را تأیید کنید
با تکمیل مهاجرت، باید نسل موفق جداول MySQL را که از طریق مدلهای جنگو ایجاد کردهایم تأیید کنیم.
برای این کار دستور زیر را در ترمینال اجرا کنید تا وارد MySQL شوید.
mysql blog_data -u djangouser
اکنون، پایگاه داده blog_data ما را انتخاب کنید. اگر پایگاه دادهای را که استفاده میکنید نمیشناسید، میتوانید همه پایگاههای داده را با SHOW DATABASES نشان دهید. در SQL
USE blog_data;
سپس برای مشاهده جداول دستور زیر را تایپ کنید.
SHOW TABLES;
این کوئری SQL باید موارد زیر را آشکار کند:
Output
+----------------------------+
| Tables_in_blog_data |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| blogsite_comment |
| blogsite_post |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
+----------------------------+
12 rows in set (0.01 sec)
از جمله جداول می توان به blogsite_comment و blogsite_post اشاره کرد. اینها مدلهایی هستند که خودمان ساخته ایم. بیایید تأیید کنیم که آنها حاوی فیلدهایی هستند که ما تعریف کرده ایم.
DESCRIBE blogsite_comment;
Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(42) | NO | | NULL | |
| email | varchar(75) | NO | | NULL | |
| website | varchar(200) | YES | | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| post_id | int | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
DESCRIBE blogsite_post;
Output
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| title | varchar(255) | NO | | NULL | |
| slug | varchar(255) | NO | UNI | NULL | |
| content | longtext | NO | | NULL | |
| created_on | datetime(6) | NO | | NULL | |
| author | longtext | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
ما تأیید کردهایم که جداول پایگاه داده با موفقیت از مهاجرتهای مدل جنگو ما تولید شدهاند.
می توانید MySQL را با CTRL + D ببندید و هنگامی که آماده خروج از محیط پایتون خود هستید، می توانید دستور غیرفعال کردن را اجرا کنید:
deactivate
غیرفعال کردن محیط برنامه نویسی شما را به خط فرمان ترمینال برمی گرداند.
نتیجه
در این آموزش، ما با موفقیت مدل هایی را برای عملکرد پایه در یک برنامه وب وبلاگ اضافه کرده ایم. شما یاد گرفته اید که چگونه مدل ها را کدنویسی کنید، چگونه مهاجرت ها کار می کند و فرآیند ترجمه مدل های جنگو به جداول پایگاه داده واقعی MySQL.