Cách tạo mô hình Django
Trong hướng dẫn trước, “ Cách tạo ứng dụng Django và kết nối nó với database ”, ta đã trình bày cách tạo database MySQL, cách tạo và khởi động ứng dụng Django cũng như cách kết nối nó với database MySQL.Trong hướng dẫn này, ta sẽ tạo các mô hình Django xác định các trường và hành vi của dữ liệu ứng dụng Blog mà ta sẽ lưu trữ. Các mô hình này ánh xạ dữ liệu từ ứng dụng Django của bạn với database . Đó là những gì Django sử dụng để tạo các bảng database thông qua API ánh xạ quan hệ đối tượng (ORM) của họ, được gọi là “mô hình”.
Yêu cầu
Hướng dẫn này là một phần của loạt bài Phát triển Django và là phần tiếp theo của loạt bài đó.
Nếu bạn chưa theo dõi loạt bài này, ta sẽ đưa ra các giả định sau:
- Bạn đã cài đặt Django version 3 trở lên.
- Bạn đã kết nối ứng dụng Django của bạn với database . Ta đang sử dụng MySQL và bạn có thể đạt được kết nối này theo phần hai của loạt bài về Django, “ Cách tạo ứng dụng Django và kết nối nó với database ”.
- Bạn đang làm việc với hệ điều hành dựa trên Unix, tốt nhất là server cloud Ubuntu 20.04 vì đây là hệ thống ta đã thử nghiệm. Nếu bạn muốn cài đặt Django trên một môi trường tương tự, vui lòng tham khảo hướng dẫn của ta , “ Cách cài đặt Django và cài đặt môi trường phát triển trên Ubuntu 20.04 .”
Vì hướng dẫn này chủ yếu liên quan đến các mô hình Django, bạn có thể làm theo ngay cả khi bạn có cài đặt hơi khác.
Bước 1 - Tạo ứng dụng Django
Để phù hợp với triết lý của Django về tính module , ta sẽ tạo một ứng dụng Django trong dự án của ta chứa tất cả các file cần thiết để tạo trang web blog.
Khi nào ta bắt đầu làm việc bằng Python và Django, ta nên kích hoạt môi trường ảo Python của bạn và chuyển vào folder root của ứng dụng. Nếu bạn đã theo dõi loạt bài này, bạn có thể đạt được điều này bằng lệnh nội dung sau.
- cd ~/my_blog_app 
- . env/bin/activate 
- cd blog 
Từ đó, hãy chạy lệnh này:
- python manage.py startapp blogsite 
Điều này sẽ tạo ứng dụng của  ta  cùng với một folder  blogsite .
Tại thời điểm này trong loạt bài hướng dẫn, bạn sẽ có cấu trúc folder sau cho dự án của bạn :
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 Tệp mà  ta  sẽ tập trung vào cho hướng dẫn này, sẽ là file  models.py , nằm trong folder  blogsite .
Bước 2 - Thêm mô hình bài đăng
 Trước tiên,  ta  cần mở và chỉnh sửa file  models.py để file  chứa mã tạo mô hình Post . Mô hình Post chứa các trường database  sau:
-  title- Tiêu đề của bài đăng trên blog.
-  slug- Nơi các URL hợp lệ được lưu trữ và tạo cho các trang web.
-  content-contentvăn bản của bài đăng trên blog.
-  created_on- Ngày tạo bài đăng.
-  author- Người đã viết bài đăng.
 Bây giờ, hãy chuyển vào folder  chứa file  models.py .
- cd ~/my_blog_app/blog/blogsite 
Sử dụng lệnh cat để hiển thị nội dung của file  trong terminal  của bạn.
- cat models.py 
Tệp phải có mã sau, mã này nhập các mô hình, cùng với chú thích mô tả những gì sẽ được đặt vào file  models.py .
from django.db import models  # Create your models here. Sử dụng editor  yêu thích của bạn, thêm mã sau vào file  models.py .  Ta  sẽ sử dụng nano làm editor   của bạn , nhưng bạn có thể sử dụng bất cứ thứ gì bạn thích.
- nano models.py 
Trong file  này, mã để nhập API mô hình đã được thêm vào,  ta  có thể tiếp tục và xóa  comment  sau đó. Sau đó,  ta  sẽ nhập slugify để tạo slugs từ các chuỗi, User của Django để xác thực và reverse từ django.urls để giúp  ta  linh hoạt hơn với việc tạo URL.
from django.db import models from django.template.defaultfilters import slugify from django.contrib.auth.models import User from django.urls import reverse Sau đó, thêm phương thức lớp vào lớp mô hình mà  ta  sẽ gọi là Post , với các trường database  sau, title , slug , content , created_on và author . Thêm những điều này bên dưới báo cáo nhập khẩu của bạn.
... 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() Tiếp theo, ta sẽ thêm chức năng tạo URL và chức năng lưu bài đăng. Điều này rất quan trọng, bởi vì điều này tạo ra một liên kết duy nhất để phù hợp với bài đăng duy nhất của ta .
...     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) Bây giờ,  ta  cần cho người mẫu biết cách sắp xếp các bài viết và hiển thị trên trang web. Logic cho điều này sẽ được thêm vào một lớp Meta lồng nhau bên trong. Lớp Meta thường chứa logic mô hình quan trọng khác không liên quan đến định nghĩa trường database .
...     class Meta:         ordering = ['created_on']          def __unicode__(self):             return self.title Cuối cùng,  ta  sẽ thêm mô hình Comment vào file  này. Điều này liên quan đến việc thêm một lớp khác có tên Comment với các models.Models trong chữ ký của nó và các trường database  sau được xác định:
-  name- Tên của người đăng comment .
-  email- Địa chỉ email của người đăng comment .
-  text- Văn bản của chính comment .
-  post- Bài đăng mà comment đã được thực hiện.
-  created_on- Thời gian comment được tạo.
... 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)  Đến đây,  models.py sẽ hoàn tất. Đảm bảo rằng file  models.py của bạn  trùng với  các thông tin sau:
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)   Đảm bảo  lưu file  . Nếu bạn đang sử dụng nano, bạn  có thể thực hiện bằng cách  gõ CTRL và X , sau đó Y , sau đó ENTER .
 Với file  models.py được  cài đặt ,  ta  có thể tiếp tục cập nhật file  settings.py .
Bước 3 - Cập nhật cài đặt
 Bây giờ  ta  đã thêm các mô hình vào ứng dụng  của bạn ,  ta  phải thông báo cho dự án  của bạn  về sự tồn tại của ứng dụng blogsite mà  ta  vừa thêm vào.  Ta  thực hiện việc này bằng cách thêm nó vào phần INSTALLED_APPS trong settings.py .
 Điều hướng đến folder  nơi settings.py của bạn.
- cd ~/my_blog_app/blog/blog 
Từ đây, hãy mở file  settings.py của bạn, chẳng hạn với nano.
-  nano settings.py 
Khi file  được mở, hãy thêm ứng dụng blogsite của bạn vào phần INSTALLED_APPS của file , như được chỉ ra bên dưới.
# Application definition INSTALLED_APPS = [     'blogsite',     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles', ] Với ứng dụng blogsite được thêm vào, bạn có thể lưu và thoát file .
Đến đây, ta đã sẵn sàng để áp dụng những thay đổi này.
Bước 4 - Thực hiện di chuyển
 Với các mô hình Post và Comment của  ta  được thêm vào, bước tiếp theo là áp dụng những thay đổi này để giản đồ database  MySQL của  ta  nhận ra chúng và tạo các bảng cần thiết.
 Đầu tiên,  ta  phải đóng gói các thay đổi mô hình  của bạn  thành các file  di chuyển riêng lẻ bằng cách sử dụng lệnh makemigrations . Các file  này tương tự như file  commits trong hệ thống kiểm soát version  như Git.
 Bây giờ, nếu bạn  chuyển  đến ~/my_blog_app/blog/blogsite/migrations và chạy ls , bạn sẽ nhận thấy rằng chỉ có một file  __init__.py . Điều này sẽ thay đổi khi  ta  thêm các di chuyển.
 Thay đổi folder  blog bằng cd , như sau:
- cd ~/my_blog_app/blog 
Sau đó chạy makemigrations lệnh trên manage.py .
- python manage.py makemigrations 
Sau đó, bạn sẽ nhận được kết quả sau trong cửa sổ terminal của bạn :
OutputMigrations for 'blogsite':   blogsite/migrations/0001_initial.py     - Create model Post     - Create model Comment  Lưu ý , khi  ta   chuyển  đến /~/my_blog_app/blog/blogsite/migrations và nó chỉ có file  __init__.py ? Nếu bây giờ  ta  cd trở lại folder  đó,  ta  sẽ nhận thấy rằng hai mục đã được thêm vào: __pycache__ và 0001_initial.py . Tệp 0001_initial.py được tạo tự động khi bạn chạy makemigrations . Một file  tương tự sẽ được tạo mỗi khi bạn chạy makemigrations .
 Chạy less 0001_initial.py từ folder  chứa nó nếu bạn muốn đọc qua những gì file  chứa.
 Bây giờ  chuyển  đến ~/my_blog_app/blog :
- cd ~/my_blog_app/blog 
Vì  ta  đã tạo một file  di chuyển,  ta  phải áp dụng các thay đổi mà các file  này mô tả cho database  bằng cách sử dụng lệnh migrate . Nhưng trước tiên, hãy kiểm tra di chuyển nào hiện đang tồn tại, sử dụng lệnh showmigrations .
- python manage.py showmigrations 
Outputadmin  [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 Bạn sẽ nhận thấy rằng tất cả các di chuyển đều được kiểm tra ngoại trừ di chuyển cho 0001_initial mà  ta  vừa tạo với các mô hình Post và Comment .
 Bây giờ, hãy kiểm tra SQL sẽ được thực thi khi  ta  thực hiện di chuyển, bằng cách sử dụng lệnh sau. Nó lấy trong quá trình di chuyển và tiêu đề của di chuyển làm đối số:
- python manage.py sqlmigrate blogsite 0001_initial 
Tiết lộ bên dưới là truy vấn SQL thực tế đang được thực hiện đằng sau mức thấp .
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`); Bây giờ ta hãy thực hiện di chuyển để chúng được áp dụng cho database MySQL của ta .
- python manage.py migrate 
Ta sẽ nhận được kết quả sau:
OutputOperations to perform:   Apply all migrations: admin, auth, blogsite, contenttypes, sessions Running migrations:   Applying blogsite.0001_initial... OK Đến đây bạn đã áp dụng thành công việc di chuyển của bạn .
Điều quan trọng cần lưu ý là có 3 lưu ý đối với việc di chuyển Django với MySQL làm chương trình backend của bạn, như đã nêu trong tài liệu Django.
- Thiếu hỗ trợ cho các giao dịch xung quanh các hoạt động thay đổi schemas . Nói cách khác, nếu quá trình di chuyển không áp dụng thành công, bạn sẽ phải bỏ chọn thủ công các thay đổi bạn đã thực hiện để thử một lần di chuyển khác. Không thể khôi phục, về điểm trước đó, trước khi thực hiện bất kỳ thay đổi nào trong quá trình di chuyển không thành công.
- Đối với hầu hết các hoạt động thay đổi schemas , MySQL sẽ viết lại đầy đủ các bảng. Trong trường hợp xấu nhất, độ phức tạp về thời gian sẽ tỷ lệ thuận với số hàng trong bảng để thêm hoặc bớt cột. Theo tài liệu Django, điều này có thể chậm đến một phút trên một triệu hàng.
- Trong MySQL, có những giới hạn nhỏ về độ dài tên cho các cột, bảng và chỉ số. Cũng có một giới hạn về kích thước kết hợp của tất cả các cột và bìa index . Trong khi một số phần mềm backend khác có thể hỗ trợ các giới hạn cao hơn được tạo trong Django, các chỉ số tương tự sẽ không được tạo với phần backend MySQL tại chỗ.
Đối với mỗi database mà bạn xem xét để sử dụng với Django, hãy đảm bảo cân nhắc những ưu và nhược điểm của từng database đó.
Bước 5 - Xác minh schemas database
Khi quá trình di chuyển hoàn tất, ta nên xác minh việc tạo thành công các bảng MySQL mà ta đã tạo thông qua các mô hình Django của ta .
 Để thực hiện việc này, hãy chạy lệnh sau trong terminal  để đăng nhập vào MySQL.  Ta  sẽ sử dụng djangouser mà  ta  đã tạo trong hướng dẫn trước .
- mysql blog_data -u djangouser 
Bây giờ, chọn blog_data database  của  ta . Nếu bạn không biết database  mình đang sử dụng, bạn có thể hiển thị tất cả các database  với SHOW DATABASES; trong SQL.
- USE blog_data; 
Sau đó gõ lệnh sau để xem các bảng.
- SHOW TABLES; 
Truy vấn SQL này sẽ tiết lộ những điều sau:
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) Trong số các bảng có blogsite_comment và blogsite_post . Đây là những mô hình mà  ta  vừa tự làm. Hãy xác thực rằng chúng chứa các trường mà  ta  đã xác định.
- 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) Ta đã xác minh các bảng database đã được tạo thành công từ việc di chuyển mô hình Django của ta .
 Bạn có thể đóng MySQL bằng CTRL + D và  khi đã sẵn sàng  rời khỏi môi trường Python  của bạn , bạn có thể chạy lệnh deactivate :
- deactivate 
Việc hủy kích hoạt môi trường lập trình của bạn sẽ đưa bạn trở lại dấu nhắc lệnh terminal .
Kết luận
 Trong hướng dẫn này,  ta  đã thêm thành công các mô hình cho chức năng cơ bản trong ứng dụng web blog. Bạn đã học cách viết mã models , cách migrations hoạt động và quá trình dịch models Django sang các bảng database  MySQL thực tế.
Các tin liên quan
 

