Hướng dẫn học Django — Phần II: Models, API và Admin

Đỗ Anh Tú
10 min readJul 24, 2016

--

Vì Django đã update lên phiên bản 2.0, và dạo này cũng đang rảnh, mình sẽ viết tiếp Series này, dĩ nhiên là dùng Django 2.0.2. OS hiện tại mình đang dùng là Ubuntu 17.10.

Từ giờ đoạn nào lấy từ Tut thì sẽ viết như thường, còn phần chú thích của mình thì sẽ cho vào trong quote kèm tag [TU].

Ok, let’s begin!

Chúng ta sẽ bắt đầu làm quen với Database, Models và đi lướt qua cả chức năng tự động tạo trang Admin cực kỳ hữu ích của Django trong phần II này.

Setup Database

[TU] Database là nơi chúng ta sẽ lưu tất cả dữ liệu cần thiết, và sẽ lấy ra sử dụng cho mục đích sau này. Thường Database sẽ được sử dụng với các site thuộc dạng “động”, nghĩa là dữ liệu thay đổi thường xuyên, và có thể thay đổi ngay lập tức dựa trên request của User.

Điều này cực kỳ tiện lợi, vì hãy cứ tưởng tượng bạn có một blog hàng trăm bài, nếu bạn làm một site static thì có nghĩa rằng bạn cũng sẽ phải ngồi chỉnh tay hàng trăm page đó!

Nhưng nếu những gì bạn cần chỉ là một vài trang không thay đổi mấy trong vài năm tới, thì làm một trang HTML tĩnh sẽ đơn giản và nhẹ hơn rất nhiều.

Giờ thì mở file mysite/settings.py lên. Đây là một Python module có level là module (đọc thêm về module-level ở đây) chứa các setting của Django.

Mặc định thì Django sẽ sử dụng SQLite. Nếu các bạn đang học Django, hoặc mới cả về Database, thì SQLite là một lựa chọn tuyệt vời. Python mặc định đã có thư viện hỗ trợ SQLite, nên bạn chẳng cần cài thêm gì cả. Nhưng khi vào một project lớn thực sự, thì bạn sẽ muốn chuyển sang những Database chuyên nghiệp hơn như PostgreSQL, để tránh tình trạng đau đầu xử lý database một khi có quá nhiều dữ liệu.

Nếu muốn dùng database khác, hãy cài đặt và tạo những thứ cơ bản của Database đó, sau đó chỉnh các key sau ở trong file settings để Django biết được rằng bạn muốn nó sử dụng chính xác Database nào.

  • ENGINE — Bạn có các lựa chọn phổ biến sau: ‘django.db.backends.sqlite3’, ‘django.db.backends.postgresql’,’django.db.backends.mysql’, hoặc ‘django.db.backends.oracle’. Còn nếu sử dụng Database khác thì hãy tham khảo ở link này.
  • NAME — Tên của Database bạn đã tạo. Nếu dùng SQLite, thì đó sẽ là đường dẫn tuyệt đối (absolute path) đến file. Giá trị mặc định os.path.join(BASE_DIR,’db.sqlite3'), sẽ lưu file ngay tại thư mục chứa project hiện tại.

Nếu bạn không dùng SQLite, hãy chú ý cung cấp đầy đủ các biến như USER, PASSWORD và HOST của Database. Xem thông tin chi tiết hơn tại ĐÂY.

[TU] Nếu đang làm một site tiếng Việt, nhớ tạo một Database hỗ trợ UTF-8 đầy đủ, kẻo sau này hối chẳng kịp!

INSTALLED_APPS sẽ chứa tên tất cả các app của Django đang và sẽ dùng. Các app này có thể sử dụng trong nhiều project khác nhau, và bạn có thể tự làm các package của mình và chia sẻ cho người khác sử dụng. Ví dụ thì có thể vào tham khảo ở Awsome Django.

Các app mặc định của Django sẽ được đặt đầu tiên:

Một số app mặc định sẽ phải sử dụng Database, nên chúng ta cần tạo các table để chúng có thể hoạt động. Nhưng tạo tay bằng SQL Query thì mệt quá, lại dễ sai lầm nữa, nên các bác làm ra Django đã viết sẵn hết cho chúng mình rồi. Chỉ cần chạy:

$ python manage.py migrate

migrate sẽ tìm trong INSTALLED_APPS xem có thằng nào dùng database không, để tạo các bảng tương ứng. Quá tiện, phải không nào. Và nó cũng tự động tạo các migrations tương ứng. Tí nữa sẽ giải thích migrations sau.

Nếu tò mò thằng Django nó tạo ra cái gì, thì vào database (hiện tại là SQLite, ví dụ sqlite3 db.sqlite3) và gõ .schema là biết liền.

Tạo các Model

Models — hay nói cách khác là mô hình database của bạn. Hãy xem tạo chúng như thế nào nào.

Triết lý đằng sau Model

Model trong Django được thiết kế dựa trên DRY (Don’t repeat yourself). Nghĩa là, chỉ có một, và một file duy nhất trong mỗi app, được dùng để định nghĩa Model của app đó. Không có ngoại lệ.

Model là cách mà các bạn định hình cơ sở dữ liệu của mình, như dữ liệu này thì lưu dạng string hay dạng integer hay loại khác, có liên quan gì tới table khác không, hay dữ liệu này sẽ được lưu để làm gì v.v…

Trong app polls của chúng ta, sẽ cần có 2 model: Question và Choice. Mỗi Question thì sẽ có câu hỏi và thời gian publish, còn mỗi Choice thì sẽ gồm 2 phần: câu trả lời và tổng số vote. Và dĩ nhiên, mỗi câu trả lời thì đều phải gắn với một câu hỏi.

Và chúng ta sẽ thể hiện điều đó trong file polls/models.py như sau:

from django.db import models


class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')


class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

Các bạn hãy chịu khó tập cách đọc code. Đấy là cách hiệu quả nhất để hiểu tận gốc, tận bản chất của vấn đề. Ở đây, mỗi model được thừa hưởng các tính chất của class django.db.models.Model. Mỗi model đều chứa một số biến, và nó đại diện cho các field trong database (Hiểu một cách đơn giản thì nó chính là các cột trong các bảng cơ sở dữ liệu)

Mỗi field đều có các tính chất riêng, như CharField để lưu các ký tự, còn DateTimeField thì lưu các dữ liệu về thời gian.

Tên của mỗi instance của một Field (vd như question_text hay pub_date) là tên của field đó, một cách thân thiện nhất với người đọc code. Bạn sẽ sử dụng tên này trong code của mình, còn database thì sẽ sử dụng như một tên của cột trong bảng.

Một vài Field sẽ có các argument bắt buộc. Ví dụ như CharField, thì bạn sẽ bắt buộc phải có max_length. Cái này sẽ được giải thích sau. Và Field cũng có thể có các argument optional nữa, ví dụ như default=0 trong phần votes.

Cuối cùng, để thể hiện sự tương quan giữa các model, chúng ta dùng ForeignKey. Nó sẽ cho Django biết rằng, mỗi Choice đều phải kết nối đến một Question nhất định. Django hỗ trợ tất cả các mối tương quan phổ biến nhất trong cơ sở dữ liệu, như: many-to-one, many-to-many, và one-to-one.

Làm cho Model hoạt động nào

Đoạn code trong file models.py bên trên chúng ta vừa viết là một bản hướng dẫn cho Django. Với nó, Django có thể:

  • Tạo các bảng tương ứng trong database cho app (CREATE TABLE trong SQL)
  • Tạo API để chúng ta tương tác dễ dàng hơn với các Model. Phần sau sẽ nói rõ hơn về cái này.

Nhưng đầu tiên, ta phải khai báo app của chúng ta với Django cái đã! Kiểu cài đặt một chương trình mới vậy.

To include the app in our project, we need to add a reference to its configuration class in the INSTALLED_APPS setting. The PollsConfigclass is in the polls/apps.py file, so its dotted path is 'polls.apps.PollsConfig'. Edit the mysite/settings.py file and add that dotted path to the INSTALLED_APPS setting. It’ll look like this:

Để khai báo “ tạm trú tạm vắng “ cho app của chúng ta, ta cần cho nó vào danh sách “quản lý” tên là INSTALLED_APPS trong settings. Class làm việc đó tên là PollsConfig ở trong file polls/apps.py, nên ta có thể dùng nó bằngpolls.apps.PollsConfig. Sửa file mysite/settings.py và thêm nó vào INSTALLED_APPS. Chúng ta sẽ có list như sau trong file settings:

INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

Giờ thì bác tổ trưởng Django đã biết có thêm một ông polls ở trong xóm rồi. Chạy lệnh sau thôi:

$ python manage.py makemigrations polls

Bạn sẽ nhìn thấy vài dòng như sau:

Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice

By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.

Migrations are how Django stores changes to your models (and thus your database schema) — they’re just files on disk. You can read the migration for your new model if you like; it’s the file polls/migrations/0001_initial.py. Don’t worry, you’re not expected to read them every time Django makes one, but they’re designed to be human-editable in case you want to manually tweak how Django changes things.

There’s a command that will run the migrations for you and manage your database schema automatically — that’s called migrate, and we’ll come to it in a moment - but first, let’s see what SQL that migration would run. The sqlmigrate command takes migration names and returns their SQL:

Khi chạy lệnh makemigrations , bạn đang xác nhận với Django rằng có vài sự thay đổi trong cách bạn cấu trúc dữ liệu, và bạn muốn lưu lại những sự thay đổi đó trong thư mục migration .

Các Migration là cách Django lưu lại lịch sử thay đổi của các Model (hay là cấu trúc cơ sở dữ liệu). Bạn có thể đọc file đó; nó nằm ở polls/migrations/0001_initial.py .

Và lệnh để chạy các migration đó và thay đổi database một cách tương ứng là migrate . Bạn có thể chạy python manage.py check để xem có lỗi gì không trước đã.

Nếu không có lỗi gì, vầy thì triển thôi.

$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK

migrate sẽ triển tất cả các migration chưa được chạy. Một cách lần lượt từ cũ đến mới.

Nên nhớ rằng, mỗi khi bạn thay đổi cấu trúc dữ liệu, hãy tạo một file migrations. Nó sẽ giúp bạn không cần phải drop database nhiều lần, tránh việc mất dữ liệu không cần thiết.

Các bước sẽ như sau:

  • Tạo thay đổi trong file models.py
  • Chạy python manage.py makemigrations để tạo file migration tương ứng.
  • Chạy python manage.py migrate để tạo các thay đổi tương ứng trong database.

Đọc kỹ hơn ở đây

Chơi với API

Phần này thì trong hướng dẫn đã chỉ quá rõ rồi, các bạn đọc thêm ở link dưới:

Có vài thứ cần rút ra sau khi thực hành đoạn trên.

  • API thực ra là một cách để bạn thử nghiệm các queryset của Django trên database. Vì Django sử dụng ORM, nên tất cả các dữ liệu của bạn đều được dùng như một object (theo đúng chất Python: mọi thứ đều là object).
  • Muốn lưu một dữ liệu nào đó, thì bạn cần dùng đến method save() của model đó. Và để xoá, ta dùng delete().
  • id của mỗi model sẽ được tạo ra tự động với thứ tự tăng dần, nếu bạn không khai báo trong code.
  • Vì tất cả các model đều là object, nên khi bạn gọi Django sẽ trả về là object. Để tránh chỉ nhìn thấy <Question: Question object>, ta sẽ def __str__(self): return self.question_text để điều chỉnh chính xác thứ ta cần biết khi query. Ở đây thì sẽ hiển thị ra nội dung câu hỏi thay vì đống <Question: Question object>
  • Ta có thể query các dữ liệu có quan hệ nữa. Dùng __ khi filter là xong.

Đọc kỹ hơn về các Queryset của Django ở đây nhé.

Django Admin

Django Admin là một app khá tiện lợi cho những ai ngại phải động vào database bằng dòng lệnh như trên. Nếu dùng Flask, bạn sẽ không có sẵn như Django đâu, mà sẽ phải tự code hoặc sử dụng package bên ngoài.

Phần Admin này khá đơn giản và rõ ràng, nếu ai từng dùng Wordpress rồi thì chẳng có gì mới lạ hết. Mặc dù nó rất là đơn giản, và bạn sẽ phải tự mình thay đổi sao cho phù hợp nhu cầu sử dụng, nhưng dù sao cũng rất tiện khi cần tham khảo dữ liệu và tương tác một cách trực quan.

Các bạn tham khảo ở link dưới:

Triết lý của việc tạo ra app Admin trong Django

Tạo ra một trang admin cho nhân viên hay khách hàng của bạn để tạo mới, thay đổi hay xoá content là một việc nhàm chán và chẳng phải sử dụng nhiều sự sáng tạo cho lắm. Để tiết kiệm thời gian, Django đã có sẵn một trang admin cho các model.

Django được tạo ra trong môi trường báo chí (bạn có thể đọc thêm về lịch sử Django, sẽ biết rằng 2 creator của Django hồi đó đều đang làm trong lĩnh vực báo chí, và Django được viết với mục đích tạo trang tin tức), nên 2 phân vùng “hậu trường” và “hiển thị” được tách ra rất rõ ràng. Quản trị website sẽ dùng hệ thống riêng để tạo, sửa và xoá các bài viết, sự kiện, kết quả thể thao v.v… và phần nội dung đó sẽ được hiển thị ở phần Public. Django giải quyết vấn đề đó bằng việc tạo ra một vùng duy nhất chỉ có các quản trị viên mới được vào để làm các việc trên.

Nên nhớ: phần Admin chỉ nên được dùng bởi các quản trị viên, không phải các user. Nếu bạn đang cho user của bạn dùng trực tiếp Admin của Django, bạn đang làm sai rồi. Hãy tự custom app Admin của riêng bạn và phân quyền rõ ràng, cẩn thận.

Few, một bài dài hơi phải không? Dù sao cũng chúc bạn hiểu hơi một chút về Django Model qua phần 2 này.

Đọc tiếp phần III

--

--