Thứ ba, 12/05/2020 | 00:00 GMT+7

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:

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 - content vă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 .

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.

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 

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_onauthor . Thêm những điều này bên dưới báo cáo nhập khẩu của bạn.

models.py
... 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 .

models.py
...     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 .

models.py
...     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.
models.py
... 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:

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)   

Đả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õ CTRLX , 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.

settings.py
# 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 PostComment 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 :

Output
Migrations 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__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
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

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 PostComment .

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:

Output
Operations 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_commentblogsite_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ế.


Tags:

Các tin liên quan