Cách tạo các Django Model
Cách tạo các Django Model
Mở đầu
Trong hướng dẫn này, ta sẽ tạo ra các mô hình (model) để xác định các trường và hành vi của dữ liệu ứng dụng Blog cần được được lưu trữ. Những mô hình này ánh xạ dữ liệu từ ứng dụng Django vào cơ sở dữ liệu và đươc Django sử dụng để tạo ra các bảng trong cơ sở dữ liệu thông qua các API object relational mapping (ORM) gọi là các "model".
Yêu cầu
Bạn cần có MySQL được cài trên server Ubuntu 16.04, cùng với kết nối đến database được thiết lập qua ứng dụng Django.
Bước 1 — Tạo ứng dụng Django
Để duy trì tính tương thích với module của Django, ta sẽ tạo một ứng dụng Django bên trong project chứa tất cả các file cần thiết để tạo một Blog.
Đầu tiên kích hoạt môi trường Python ảo:
cd ~/my_blog_app env/bin/activate
cd blog
Sau đó chạy lệnh:
python manage.py startapp blogsite
Đến đây bạn đã có cấu trúc dữ liệu cho project của mình:
my_blog_app/
└── blog
├── blog
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-35.pyc
│ │ ├── settings.cpython-35.pyc
│ │ ├── urls.cpython-35.pyc
│ │ └── wsgi.cpython-35.pyc
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── blogsite
│ ├── admin.py
│ ├── apps.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
Ta sẽ tập trung vào file models.py
trong bài viết này.
Bước 2 — Thêm các Posts Model
Đầu tiên ta cần mở file models.py
, vì nó chứa đoạn mã nguồn giúp ta tạ ra một Post
model. Một Post
model sẽ chứa những thuộc tính sau của database:
title
— Tiêu đề của blog.slug
— Nơi các URL được lưu và cung cấp cho cac trang webcontent
— Các thành phần của bài blog post.created_on
— Ngày bài post được tạo.author
— Tác giả bài post.
Thay đổi thư mục chứa models.py
:
cd ~/my_blog_app/blog/blogsite
Dùng lệnh cat
để hiển thị các thành phần của file trên terminal.
cat models.py
File này sẽ chứa những dòng code có nhiệm vụ import các model, cùng các comment miêu tả các thành phần của file.
from django.db import models# Create your models here.
Dùng nano để thay đổi nội dung của file models.py
với lệnh:
nano models.py
Trong file này, mã import các model API đã được thêm vào, nên đầu tiên ta chỉ cần xóa dòng comment bên dưới nó. Sau đó ta sẽ import slugify
để tạo ra các mã từ các chuỗi, mà User
của Django dùng nó để xác thực.
from django.db import modelsfrom django.template.defaultfilters import slugifyfrom django.contrib.auth.models import User
Sau đó ta sẽ thêm vào class Post
các thuộc tính dựa trên các trường của database như title
, slug
, content
, created_on
và author
.
...classPost(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 tính năng sinh ra các URL và các chức năng để lưu bài đăng:
...@models.permalinkdefget_absolute_url(self):return ('blog_post_detail', (),{'slug': self.slug,
})
defsave(self, *args, **kwargs):ifnot self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
Giờ ta sẽ cho model biết các bài post sẽ được sắp xếp , và hiển thị trên trang web như thế nào. Để làm vậy ta sẽ cần một class Meta
được lồng bên trong file cấu hình. Class này chứa những logic cơ bản liên quan đến việc xử lí các trường của database.
...
classMeta: ordering = ['created_on']
def__unicode__(self):return self.title
Cuối cùng, ta sẽ thêm vào Comment
model. Model này bao gồm một class Comment
chứa models.Models
bên trong nó cùng các trường sau:
name
— Tên người đăng comment.email
— Địa chỉ email của người đăng.text
— Nội dung comment.post
— Bài post mà comment được đăng.created_on
— Thời gian comment được tạo.
...classComment(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)
File models.py
sau khi được chỉnh sửa sẽ trông như sau:
from django.db import modelsfrom django.template.defaultfilters import slugifyfrom django.contrib.auth.models import UserclassPost(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()
@models.permalinkdefget_absolute_url(self):return ('blog_post_detail', (),{'slug': self.slug,
})
defsave(self, *args, **kwargs):ifnot self.slug:
self.slug = slugify(self.title)
super(Post, self).save(*args, **kwargs)
classMeta: ordering = ['created_on']
def__unicode__(self):return self.titleclassComment(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)
Lưu và đóng file
Bước 3 — Update các cài đặt
Sau khi thêm các model vào ứng dụng, ta cần cho project khả năng tương tác với úng dung blogsite
vừa được tạo. Ta sẽ thực hiện điều này bằng việc điều chỉnh mục INSTALLED_APPS
trong file settings.py
.
Chuyển đến thư mục chứa file settings.py
.
cd ~/my_blog_app/blog/blog
Mở file settings.py
với nano bằng lệnh nano settings.py
.
Sau khi mở file, thêm ưng dụng blogsite
vào mục INSTALLED_APPS
như sau:
# Application definitionINSTALLED_APPS = [
'blogsite','django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Lưu và đóng file.
Bước 4 — Tạo các Migration
Với các model Post
và Comment
được thêm vào, bước tiếp theo là áp dụng những thay đổi để MySQL
database nhận dạng được chúng tà tạo ra các bảng theo yêu cầu.
Đầu tiên ta sẽ cần log in vào MySQL server.
Note: Trong ví dụ này, ta sẽ sử dụng user root
và không có mật khẩu, nhưng bạn nên dùng username và password của riêng bạn.
mysql blog_data -u root
Với lệnh SHOW DATABASES;
bạn sẽ thu được output như sau:
Output+--------------------+
| Database |
+--------------------+
| information_schema |
| blog_data |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
Chọn database blog_data
:
USE blog_data;
Hiển thị danh sách các bảng trong blog_data
:
SHOW TABLES;
OutputEmpty set (0.00 sec)
Không có bảng nào được hiển thị vì ta chưa tạo ra migration nào. Nhưng bất cứ khi nào ta tạo ra các migration, chúng sẽ được hiển thị trên các bảng được tạo bởi Django.
Giờ ta sẽ tạo ra migration áp dụng những cài đặt đã được ta cấu hình sẵn ở models.py
.
Thoát My SQL với tổ hợp phím CTRL
+ D
.
Đầu tiên ta cần đóng gói các thay đổi của model thành các file migration riêng biệt với lệnh makemigrations
. Các file này gần giống với các commits
trong các hệ điều khiển dữ liệu như git
.
Giờ nếu truy cập vào ~/my_blog_app/blog/blogsite/migrations
và chạy lệnh ls
, bạn sẽ thấy có một file duy nhất là __init__.py
.
Thay đổi thư mục của blog với lệnh cd
, rồi tạo file migration với lệnh makemigrations
cd ~/my_blog_app/blog
python manage.py makemigrations
Bạn sẽ thu được Output như sau:
OutputMigrations for 'blogsite':
blogsite/migrations/0001_initial.py
- Create model Comment
- Create model Post
- Add field post to comment
Lần đầu khi chuyển đến thư mục /~/my_blog_app/blog/blogsite/migrations
, nó chỉ chứa một file duy nhất là __init__.py
. Nếu giờ ta dùng lệnh cd
để truy cập trở lại thư mục ấy, sẽ có thêm 2 file được thêm vào, __pycache__
và 0001_initial.py
. File 0001_initial.py
được tạo tự động khi chạy lệnh makemigrations
, và mỗi lần bạn chạy lệnh makemigrations
, một file như thế sẽ được tạo ra ở thư mục này.
Giờ hãy chuyển sang thư mục ~/my_blog_app/blog
.
Vì ta đã có một file migration, ta cần phải áp dụng những cài đặt trên các file này lên database với lệnh migrate
.
Đầu tiê hãy dùng showmigrations
command để hiển thị danh sách các migration hiện tại:
python manage.py showmigrations
Outputadmin
[ ] 0001_initial
[ ] 0002_logentry_remove_auto_add
auth
[ ] 0001_initial
[ ] 0002_alter_permission_name_max_length
[ ] 0003_alter_user_email_max_length
[ ] 0004_alter_user_username_opts
[ ] 0005_alter_user_last_login_null
[ ] 0006_require_contenttypes_0002
[ ] 0007_alter_validators_add_error_messages
[ ] 0008_alter_user_username_max_length
[ ] 0009_alter_user_last_name_max_length
blogsite
[ ] 0001_initial
contenttypes
[ ] 0001_initial
[ ] 0002_remove_content_type_name
sessions
[ ] 0001_initial
Bạn sẽ thấy migration blogsite
, chứa migration 0001_initial
cho các model Post
và Comment
được hiển thị.
Giờ hãy xem các lệnh SQL
được triển khai khi ta tạo ra migration, với các lệnh dưới đây.
python manage.py sqlmigrate blogsite 0001_initial
Đây là các lệnh SQL được thực hiện trên database sau lệnh trên:
BEGIN;
--
-- 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);
--
-- 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);
--
-- Add field post to comment
--
ALTER TABLE `blogsite_comment` ADD COLUMN `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`);
COMMIT;
Giờ hãy biểu diễn các migration để chúng được áp dụng vào MySQL database.
python manage.py migrate
OutputOperations to perform:
Apply all migrations: admin, auth, blogsite, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying blogsite.0001_initial... OK
Applying sessions.0001_initial... OK
Vậy là các migration đã được áp dụng thành công.
Ghi nhớ 3 cảnh báo sau về việc áp dụng các Django migration trên backend là MySQL:
- Thiếu sự hỗ trợ khi việc áp dụng migration thất bại. Nói cách khác, nếu một migration được áp dụng không thành công, bạn sẽ phải tự gỡ bỏ thay đổi bạn đã thực hiện để thực hiện migration khác mà không thể rollback đến trạng thái trước đó của database.
- Với hầu hết các hoạt động làm thay đổi sơ đồ của MySQL sẽ hoàn toàn viết lại bảng. Trong trường hợp xấu nhất, độ phức tạp thời gian có tỷ lệ thuận với số lượng hàng trong bảng khi muốn thêm hoặc xóa cột. Theo tài liệu hướng dẫn từ Django, khoảng thời gian trễ này có thể lên đến một phút cho một triệu hàng.
- Trong MySQL, có những giới hạn nhỏ của độ dài tên cho các cột, bảng và các chỉ số. Ngoài ra còn có một giới hạn về kích thước tổng cộng của tất cả các cột với chỉ số của chúng. Trong khi một số backend khác có thể hỗ trợ giới hạn cao hơn tạo ra trong Django, các chỉ số tương tự sẽ không được với một backend MySQL.
Hãy cân nhắc các ưu nhược điểm với từng database để sử dụng Django hiệu quả.
Bước 5 — Kiểm tra Lược đồ Database
Đầu tiên, log in vào MySQL.
mysql blog_data -u root
Hiển thị các databasei:
SHOW DATABASES;
Chọn database blog_data
:
USE blog_data;
Hiển thị các bảng:
SHOW TABLES;
Bạn sẽ thu được:
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 |
+----------------------------+
Bạn sẽ thấy các model blogsite_comment
và blogsite_post
vừa được tạo. Giờ hãy kiểm tả xem chúng có chứa những trường như ta đã thiết lập hay không
DESCRIBE blogsite_comment;
Output+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | 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(11) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)
DESCRIBE blogsite_post;
Output:+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | 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.01 sec)
Thoát MySQL với tổ hợp phím CTRL
+ D
và deactivate
môi trường Python:
deactivate
Tổng kết
Trong bài viết này, ta đã thêm vào các model với những chức năng cơ bản cho một ứng dụng web blog. Bạn đã biết cách code các models
, cách các migrations
hoạt động và quá trình xử lí các Django models
qua các bảng của MySQL
database.