Học Django | Giới thiệu về Django

Trước khi bạn bắt đầu

Mỗi cuộc hành trình vĩ đại luôn bắt đầu với một bước khiêm tốn. Trước khi chúng ta có thể làm những điều tuyệt vời với Django, chúng ta cần chuẩn bị một môi trường để làm việc với Django.

Cài đặt Python

Trước khi sử dụng phiên bản Django 3 trở lên, bạn cần cài đặt Python 3 trên máy tính. Hệ điều hành Mac và Linux thường có một số phiên bản Python đã cài đặt sẵn, nhưng tốt nhất hãy luôn cài đặt phiên bản mới nhất. Trên Mac, dành cho người dùng Homebrew, bạn chỉ cần nhập lệnh sau:

$ brew install python
Code language: Bash (bash)

Trên các bản phân phối Linux dựa trên Debian, bạn nhập lệnh:

$ sudo apt install python3 python3-pip
Code language: Bash (bash)

Đối với Windows, bạn có thể tải xuống trình cài đặt Python tại trang chủ của Python. Sau khi đã tải xong trình cài đặt, nhấn đúp chuột vào nó để chạy, sau đó làm theo các hướng dẫn. Đảm bảo chọn Add Python 3.x to PATH.

Sau khi cài đặt, từ Command Prompt, bạn có thể dùng lệnh python để khởi chạy trình thông dịch Python.

Lưu ý rằng trên MacOS và Linux, tùy thuộc cấu hình của bạn, lệnh python có thể khởi chạy Python 2 hoặc Python 3. Để chắc chắn chạy Python 3 hãy sử dụng lệnh python3. Trên Windows, bạn chỉ cần chạy python vì nó luôn khởi chạy Python 3.

Tương tự với lệnh pip. Trên MacOS và Linux, sử dụng pip3; trên Windows, chỉ cần dùng pip.

Cài đặt trình soạn thảo

Bạn cần một trình soạn thảo mã để viết mã Python cho dự án Django. Có nhiều sự lựa chọn, bạn có thể sử dụng PyCharm hoặc Visual Studio Code.

Tạo môi trường Python ảo

Măc dù không bắt buộc, bạn nên sử dụng môi trường Python cho dự án Django của mình, nó sẽ giữ các gói Python mà dự án Django sử dụng tách biệt với các gói hệ thống.

Trên MacOS và Linux, để tạo môi trường ảo, bạn cần cài đặt gói Python có tên virtualenv thông qua pip3:

$ pip3 install virtualenv
Code language: Bash (bash)

Sau đó chúng ta có thể tạo môi trường Python ảo trong thư mục hiện:

$ python3 -m virtualenv <tên_môi_trường>
Code language: Bash (bash)

Việc tiếp theo là cài đặt môi trường ảo này làm môi trường Python mặc định của Terminal thông qua lệnh source:

$ source <tên_môi_trường>/bin/activate
Code language: Bash (bash)

Trên Windows, chúng ta không cần cài đặt thêm virtualenv mà chỉ cần sử dụng gói venv đã được cài đặt sẵn khi ta cài đặt Python. Cách tạo môi trường ảo bằng venv tương tự như virtualenv:

> python -m venv <tên_môi_trường>
Code language: Bash (bash)

Để cài đặt môi trường ảo này làm môi trường Python mặc định của Command Prompt chỉ cần chạy một kịch bản có tên activate bên trong môi trường ảo vừa tạo:

> <tên_môi_trường>\Scripts\activate
Code language: Bash (bash)

Trên MacOS, Linux và Windows, bạn biết được môi trường ảo đã được kích hoạt bởi vì tên của nó đặt trong dấu ngoặc, trước dấu nhắc lệnh.

(tên_môi_trường) $
Code language: Bash (bash)

Cài đặt Django

Sau khi tạo và kích hoạt môi trường Python ảo, ta sử dụng các lệnh pip3 hoặc pip (tùy thuộc vào hệ điều hành của bạn) để cài đặt Django vào trong môi trường này:

(tên_môi_trường) $ pip3 install django
Code language: Bash (bash)

Django 3.0 và Django 3.1

Từ Django 3.1 trở đi, các tác giả đã thay đổi phương pháp tạo và kết hợp các đường dẫn trong settings.py.

Trong các phiên bản trước đó, biến BASE_DIR (đường dẫn tới dự án) được tạo dưới dạng chuỗi như sau:

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Code language: Python (python)

Gói os đã được nạp vào settings.py. Các đường dẫn được kết hợp với nhau bằng hàm os.path.join():

STATIC_ROOT = os.path.join(BASE_DIR, "static")
Code language: Python (python)

Trong Django 3.1, BASE_DIR là đối tượng pathlib.Path được tạo như sau:

BASE_DIR = Path(__file__).resolve().parent.parent
Code language: Python (python)

Các đường dẫn được kết hợp với nhau bằng toán tử / (chia) đã được pathlib.Path ghi đè:

STATIC_ROOT = BASE_DIR / "static"
Code language: Python (python)

Cài đặt DB Browser for SQLite

Django sử dụng hệ quản trị cơ sở dữ liệu SQLite làm mặc định. Django cung cấp sẵn giao diện dòng lệnh để truy cập cơ sở dữ liệu, nhưng các ứng dụng GUI làm cho công việc duyệt dữ liệu trở nên thân thiện hơn.

Công cụ mà chúng ta sẽ sử dụng là DB Browser for SQLite, hay gọi tắt là DB Browser. Nó là một ứng dụng GUI đa nền tảng có thể cài đặt trên Windows, MacOS và Linux.

Tạo dự án và ứng dụng Django

Trước khi đi sâu vào lý thuyết về mô hình hoạt động của Django và các HTTP request, chúng ta sẽ học cách thiết lập và chạy một dự án Django.

Dự án Django là một thư mục chứa tất cả các dữ liệu cho dự án của bạn gồm mã nguồn, các cài đặt, các template và nội dung. Nó được tạo nên bằng cách chạy lệnh django-admin trên dòng lệnh với đối số startproject và cung cấp thêm tên dự án. Chẳng hạn lệnh sau đó sẽ tạo ra dự án Django có tên myproject:

$ django-admin startproject myproject
Code language: Bash (bash)

Một thư mục có tên myproject được tạo ra để chứa toàn bộ dự án, bên trong thư mục này ta thấy một thư mục cùng tên và tệp manage.py:

myproject |__ manage.py |__ myproject

manage.py là một tập lệnh Python được thực thi tại dòng lệnh để tương tác với dự án của bạn. Chúng ta sẽ sử dụng nó để khởi động máy chủ Django Dev Server để hiển thị dự án trên trình duyệt. Giống như django-admin các lệnh được viết trong Terminal/Command Prompt, nhưng manage.py không thể gọi trực tiếp mà phải thực thi qua trình thông dịch Python (qua lệnh python hoặc python3). Chẳng hạn, bên trong thư mục dự án, chạy lệnh:

$ python3 manage.py runserver
Code language: Bash (bash)

Thao tác này truyền lệnh runserver đến tập lệnh manage.py để khởi động Django Dev Server. Chúng ta sẽ xem thêm các lệnh mà manage.py chấp nhận trong phần tiếp theo. Các lệnh mà manage.py cung cấp được gọi là các lệnh quản lý.

Lệnh startproject cũng tạo một thư mục cùng tên với dự án, trong trường hợp này là myproject. Đây là một gói Python chứa tệp cài đặt settings.py và một số tệp cấu hình khác mà dự án của bạn cần để chạy.

Sau khi đã tạo dự án Django, điều tiếp theo cần làm là tạo một ứng dụng Django. Chúng ta nên cố gắng tách dự án Django của mình thành nhiều ứng dụng khác nhau, được nhóm theo chức năng. Ứng dụng Django được tạo bởi lệnh quản lý startapp, ví dụ:

$ python3 manage.py startapp myapp
Code language: Bash (bash)

Lệnh này tạo ra thư mục ứng dụng (myapp) bên trong thư mục dự án. Django tự động thêm các tệp cần thiết cho ứng dụng, sẵn sàng cho bạn thay đổi chúng trong quá trình phát triển ứng dụng.

Bài tập 1.01: Tạo dự án, ứng dụng và khởi động Django Dev Server

Trong loạt bài học này, chúng ta sẽ xây dựng một trang web đánh giá sách có tên Bookr. Trong bài tập này, bạn sẽ khởi tạo dự án, xem nó có hoạt động không bằng cách khởi động máy chủ phát triển Django Dev Server và cuối cùng tạo ứng dụng đầu tiên của dự án có tên reviews.

1. Mở Terminal/Command Prompt, tạo và kích hoạt môi trường Python ảo sau đó cài đặt Django trong môi trường này. Việc tiếp theo là tạo dự án bookr bằng lệnh sau:

$ django-admin startproject bookr
Code language: Bash (bash)

Lệnh này không in ra đầu ra nào nhưng sẽ tạo một thư mục có tên bookr bên trong thư mục hiện tại mà bạn đã chạy lệnh. Bạn có thể nhìn vào bên trong thư mục này và xem cấu trúc của nó: gồm tệp manage.py và thư mục cùng tên bookr.

2. Bây giờ chúng ta có thể kiểm tra xem dự án Django có được thiết lập chính xác hay không bằng cách khởi động máy chủ Django Dev Server. Trong Terminal/Command Prompt, chuyển đến thư mục bookr vừa tạo ra (bằng lệnh cd) và chạy lệnh quản lý runserver:

$ python3 manage.py runserver
Code language: Bash (bash)

Lệnh này in ra đầu ra như sau:

Watching for file changes with StatReloader Performing system checks... System check identified no issues (0 silenced). You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them. September 14, 2019 - 09:40:45 Django version 3.0a1, using settings 'bookr.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Code language: Bash (bash)

3. Mở trình duyệt web và truy cập http://127.0.0.1:8000/, thao tác này sẽ hiển thị cho bạn màn hình chào mừng của Django. Nếu bạn thấy nó, bạn biết dự án Django đã được tạo thành công và hiện tại tất cả đều hoạt động tốt:

Màn hình chào mừng của Django

4. Quay lại Terminal/Command Prompt và dừng máy chủ phát triển Django Web Server bằng cách bấm tổ hợp phím Ctrl + C.

5. Bây giờ chúng ta sẽ tạo ứng dụng reviews cho dự án bookr. Trong Terminal/Command Prompt của bạn, đảm bảo rằng đang ở trong thư mục bookr của dự án, sau đó thực hiện lệnh quản lý startapp để tạo ứng dụng reviews, như sau:

$ python3 manage.py startapp reviews
Code language: Bash (bash)

Lệnh trên không in ra gì nếu thực hiện thành công, nhưng một ứng dụng reviews đã được tạo. Bạn có thể nhìn vào trong thư mục reviews mới được tạo ra để xem các tệp và thư mục đã được tạo: migrations, admin.py, models.py

Model View Template

Một mẫu thiết kế phổ biến trong thiết kế ứng dụng là Model View Controller (MVC), trong đó model của ứng dụng (dữ liệu của nó) được hiển thị trong một hoặc nhiều view và một controller sẽ điều khiển sự tương tác giữa modelview. Django dựa theo một mô hình tương tự gọi là Model View Template (MVT).

Giống như MVC, MVT cũng sử dụng các model để lưu trữ dữ liệu. Tuy nhiên với MVT, một view sẽ truy vấn một model để lấy dữ liệu và đó sử dụng một template để render dữ liệu này. Thông thường, với các ngôn ngữ MVC, tất cả ba thành phần cần được viết bẳng cùng một ngôn ngữ lập trình. Với MVT, template có thể viết bằng ngôn ngữ khác. Trong trường hợp của Django, các modelview được viết bằng Python còn template được viết bằng HTML.

Các model

Các model xác định dữ liệu cho ứng dụng của bạn và cung cấp một lớp trừu tượng để truy cập cơ sở dữ liệu SQL thông qua một Object Relational Mapper viết tắt là ORM. ORM cho phép bạn định nghĩa bảng dữ liệu bằng Python mà không cần phải biết về ngôn ngữ SQL, Django sẽ tự động phân tích model và tạo ra mã SQL cho bạn.

Thông thường, khi truy vấn cơ sở dữ liệu bằng SQL, kết quả trả về là các đối tượng Python nguyên thủy (chuỗi, danh sách, số nguyên, số thực…). Khi sử dụng ORM, kết quả được tự động chuyển đổi thành các thực thể của model mà bạn đã định nghĩa.

Các view

Các view trong Django là nơi mà ta viết hầu hết các lôgic cho ứng dụng. Khi một người dùng truy cập trang web của bạn, trình duyệt web của họ sẽ gửi yêu cầu tới trang web này. View là một hàm do bạn viết, sẽ nhận được yêu cầu này từ trình duyệt dưới dạng một đối tượng HttpRequest và trả về một đối tượng HttpResponse – chứa tất cả các thông tin được trả về cho trình duyệt.

Các template

Template là một tệp HTML có chứa những placeholder (bộ giữ chỗ) đặc biệt. Khi được render cùng với dữ liệu, các placeholder được thay thế bằng các biến mà view cung cấp.

Giới thiệu về HTTP

Bạn đã được giới thiệu về MVT trong Django, chúng ta có thể xem cách Django xử lý một HTTP request và tạo một HTTP response. Nhưng trước tiên chúng ta cần biết HTTP request và HTTP response là gì và thông tin nào chúng chứa đựng.

Giả sử ai đó muốn truy cập trang web. Họ nhập URL của trang hoặc nhấn vào một liên kết đến trang. Trình duyệt web của bạn tạo ra một HTTP request, và gửi nó tới máy chủ lưu trữ trang web của bạn. Sau khi máy chủ web nhận được HTTP request từ trình duyệt, nó có thể hiểu và sau đó gửi lại một HTTP response.

Một HTTP request bao gồm 4 phần chính: method (phương thức), đường dẫn (path), các header (tiêu đề) và phần thân (body). Một số yêu cầu không có phần thân. Nếu bạn chỉ truy cập một trang web, trình duyệt của bạn sẽ không gửi phần thân, trong khi nếu bạn gửi thông tin qua một form (ví dụ đăng một status, hoặc thực hiện tìm kiếm) thì request của bạn sẽ có phần thân chứa dữ liệu của form. Chúng ta sẽ minh họa bằng hai ví dụ.

Ví dụ đầu tiên là khi bạn truy cập trang web có địa chỉ https://www.example.com/page, đằng sau hậu trường, đây là những gì nó gửi tới trình duyệt:

GET /page HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:15.0) Firefox/15.0.1 Cookie: sessid=abc123def456
Code language: HTTP (http)

Dòng đầu tiên chứa phương thức (GET) và đường dẫn (/page) và phiên bản HTTP (1.1). Nhiều phương thức HTTP khác nhau có thể được sử dụng, tùy thuộc vào cách bạn muốn tương tác với trang web. Một số phương thức phổ biến là GET (khi cần truy cập trang), POST (khi cần gửi dữ liệu đến trang), PUT (khi cần tạo dữ liệu) và DELETE (khi cần xóa dữ liệu).

Từ dòng thứ hai trở đi là các header. Các header chứa siêu dữ liệu của request. Mỗi header được viết trên một dòng, tên header và giá trị được phân cách nhau bằng dấu hai chấm. Hầu hết các header là không bắt buộc (ngoại trừ Host). Tên của header không phân biệt chữ hoa chữ thường. Ví dụ của chúng ta có 3 header sau đây:

  • Host: đây là header bắt buộc. Nó cần phải có để máy chủ web biết trang web hoặc ứng dụng nào cần phải xử lý request này.
  • User-Agent: là một chuỗi mà trinh duyệt gửi đến máy chủ để cho biết phiên bản của nó và hệ điều hành. Ứng dụng máy chủ có thể sử dụng thông tin này để phân phát các trang khác nhau cho các thiết bị khác nhau, chẳng hạn, một trang dành cho máy tính, một trang dành cho thiết bị di động.
  • Cookie: bạn có thể đã thấy một thông báo khi truy cập một trang web cho bạn biết nó đang lưu trữ một cookie trong trình duyệt. Đây là những mảnh thông tin nhỏ mà một trang web có thể lưu trữ trong trình duyệt của bạn; có thể được sử dụng để xác định bạn hoặc lưu cài đặt khi bạn quay lại trang. Nếu bạn đang tự hỏi về cách trình duyệt của bạn gửi lại những cookie này cho máy chủ thì nó thông qua header này.

Còn nhiều tiêu đề khác nữa, chẳng hạn Authorization dùng để xác thực; Accept nói cho máy chủ biết loại dữ liệu mà máy khách chấp nhận; Accept-Language cho máy chủ biết ngôn ngữ mà máy khách chấp nhận. Bạn cũng có thể tự định nghĩa những header riêng cho ứng dụng của mình và chỉ các ứng dụng của bạn mới biết cách để phản hồi lại những header này.

Ví dụ thứ hai, bạn truy cập https://www.example.com/login và nó sẽ hiển thị một biểu mẫu để bạn nhập tên người dùng và mật khẩu. Sau khi bạn bấm nút Đăng nhập, đây là HTTP request được gửi đến máy chủ:

POST /login HTTP/1.1 Host: www.example.com Content-Type: application/x-www-form-urlencoded Content-Length: 32 username=user1&password=password1
Code language: HTTP (http)

Phương thức bây giờ là POST và hai header mới là

  • Conent-Type: cho máy chủ biết loại dữ liệu được chứa trong phần thân của request. Trong trường hợp trên application/x-www-form-urlencoded cho biết phần thân là một tập các cặp khóa-giá trị biểu diễn dữ liệu của form. Ngoài ra máy khác còn có thể sử dụng header này để cho máy chủ biết nó đang gửi các loại dữ liệu khác, chẳng hạn như JSON hoặc XML.
  • Content-Length: cho máy chủ biết chiều dài nội dung của phần thân.

Các tiêu đề được ngăn cách phần thân bởi một dòng trống. Bằng cách nhìn vào ví dụ, bạn có thể nhận biết cách dữ liệu của form được mã hóa: username có giá trị userpassword có giá trị password1.

Một HTTP response trông tương tự một request và gồm 3 phần chính: trạng thái (status), các header và phần thân. Tùy thuộc vào loại response (phản hồi) có thể có hoặc không có phần thân.

Ví dụ đầu tiên về một HTTP response có trạng thái thành công:

HTTP/1.1 200 OK Server: nginx Content-Length: 18132 Content-Type: text/html Set-Cookie: sessid=abc123def456 <!DOCTYPE html><html><head>...
Code language: HTML, XML (xml)

Dòng đầu tiên là phiên bản HTTP (1.1), mã trạng thái (200), sau đó là văn bản mô tả ý nghĩa của mã trạng thái (OK – tức yêu cầu đã thành công). Các dòng từ 2 đến 5 chứa các header:

  • Server: tương tự nhưng ngược lại với User-Agent bên HTTP request – máy chủ cho máy khách biết nó đang chạy phần mềm nào để gửi phàn hồi.
  • Content-Length: máy khách sử dụng giá trị này để xác định lượng dữ liệu máy chủ gửi về.
  • Content-Type: máy chủ sử dụng header này để chỉ ra cho máy khác biết loại dữ liệu mà nó đang gửi. Sau đó, máy khách có thể chọn cách nó sẽ hiển thị loại dữ liệu này – chẳng hạn, một hình ảnh phải được hiển thị khác với một tệp HTML.
  • Set-Cookie: chúng ta đã thấy trong ví dụ đầu tiên về HTTP request cách mà máy khách gửi cookie đến máy chủ. Đây là header tương ứng mà máy chủ gửi để lưu cookie trên trình duyệt.

Sau các header là một dòng trống, và sau đó là phần thân của response. Chúng ta chỉ hiển thị vài ký tự đầu tiên của mã HTML trong tổng số 18132 ký tự mà máy chủ đã gửi.

Ví dụ thứ hai về HTTP response được trả về nếu một trang web được yêu cầu không thể tìm thấy:

HTTP/1.1 404 Not Found Server: nginx Content-Length: 55 Content-Type: text/html <!DOCTYPE html><html><body>Page Not Found</body></html>
Code language: HTML, XML (xml)

Nó tương tự ví dụ trước, nhưng trạng thái bây giờ là 404 Not Found. Nếu bạn đã từng duyệt web và nhận được lỗi 404, đây là loại phản hồi mà trình duyệt của bạn nhận được. Các mã trạng thái được nhóm theo những loại sau:

  • 100-199: máy chủ gửi mã trạng thái trong phạm vi này để cho biết giao thức đã thay đổi hoặc cần nhiều dữ liệu hơn. Bạn không phải quá lo lắng về những mã trong phạm vi này.
  • 200-299: mã trạng thái trong phạm vi này cho biết việc xử lý yêu cầu đã thành công. Mã phổ biến nhất là 200 OK.
  • 300-399: mã trạng thái trong phạm vi này có nghĩa là trang bạn đang yêu cầu đã chuyển đến một địa chỉ khác. Một ví dụ là các dịch vụ rút ngắn URL sẽ chuyển hướng bạn từ URL ngắn sang URL đầy đủ. Các mã phổ biến nhất là 301 Moved Permanently hoặc 302 Found. Khi gửi phản hồi chuyển hướng loại này, máy chủ cũng sẽ thêm vào một header có tên Location chứa URL sẽ được chuyển đến.
  • 400-499: mã trạng thái trong phạm vi này có nghĩa là yêu cầu không thể được xử lý vì có sự cố đối với những gì máy khách đã gửi. Nó ngược với những yêu cầu không thể được xử lý do sự cố trên máy chủ. Chúng ta đã thấy 404 Not Found, nguyên nhân là do yêu cầu không hợp lệ vì máy khác đang yêu cầu một trang không tồn tại. Một số trạng thái phổ biến khác là 401 Unauthorized (người dùng chưa đăng nhập) và 403 Forbidden (người dùng không được cấp quyền truy cập tài nguyên).
  • 500-599: mã trạng thái trong phạm vi này cho biết lỗi là do phía máy chủ. Các máy khách không nên mong đợi có thể điều chỉnh yêu cầu để khắc phục sự cố kiểu này. Khi làm việc với Django, trạng thái lỗi máy chủ phổ biến nhất là 500 Internal Server Error. Nó xuất hiện khi mã của bạn tạo ra một ngoại lệ không được xử lý. Một lỗi phổ biến khác là 504 Gateway Timeout, xảy ra khi mã của bạn mất quá nhiều thời gian để xử lý yêu cầu từ máy khách. Các mã khác là 502 Bad Gateway503 Service Unavailale.

Đây chỉ là một số mã trạng thái HTTP phổ biến. Bạn có thể tìm thấy danh sách đầy đủ tại trang chủ Mozilla.

Nếu đây là lần đầu tiên bạn được làm quen với giao thức HTTP, có khá nhiều thông tin cần tiếp nhận. May mắn thay, Django thực hiện tất cả công việc khó khắn đó và gói gọn dữ liệu từ HTTP request vào đối tượng HttpRequest. Hầu hết thời gian, bạn không cần biết về phần lớn các thông tin trong HttpRequest, nhưng nó luôn có sẵn nếu bạn cần nó. Tương tự như vậy khi gửi HTTP response, Django đóng gói thông tin của HTTP Response vào trong đối tượng HttpResponse. Thông thường bạn chỉ cần định nghĩa nội dung đề trả về, nhưng bạn cũng có thể tự do đặt mã trạng thái và các header.

Dự án Django

Chúng ta đã được giới thiệu về dự án Django trong phần trước. Nhắc lại về những gì xảy ra khi ta chạy startproject (cho một dự án có tên myproject): lệnh này tạo một thư mục myproject với một tệp manage.py và thư mục cùng tên myproject. Bây giờ chúng ta sẽ nói về chúng một cách chi tiết hơn.

manage.py

Đây là tập lệnh được sử dụng để quản lý dự án Django. Hầu hết các lệnh sử dụng để tương tác với dự án sẽ được cung cấp bởi tệp lệnh này. Các lệnh được cung cấp như đối số của manage.py; ví dụ, nếu chúng ta chạy lệnh manage.py runserver, có nghĩa là chúng ta chạy lệnh tập lệnh manage.py như sau:

$ python3 manage.py runserver
Code language: Bash (bash)

Có nhiều lệnh hữu ích mà manage.py cung cấp. Bạn sẽ được giới thiệu về chúng chi tiết hơn trong suốt các bài hướng dẫn này; một số lệnh phổ biến hơn được liệt kê dưới đây:

  • runserver: tạo một ứng dụng Django mới trong dự án của bạn.
  • shell: khởi động trình thông dịch Python với toàn bộ dự án Django đã được nạp sẵn.
  • dbshell: tương tác với cơ sở dữ liệu qua dòng lệnh.
  • makemigrations: tạo các migration.
  • migrate: áp dụng các migration.
  • test: chạy các bài kiểm tra tự động mà bạn đã viết.

Thư mục myproject

Một thư mục cùng tên với dự án được tạo bởi startprojectmyproject. Nó thực tế là một gói Python chứa các cài đặt cho dự án, một số tệp cấu hình cho máy chủ web và các ánh xạ URL toàn cục. Bên trong thư mục myproject là 5 tệp:

  • __init__.py
  • asgi.py
  • settings.py
  • urls.py
  • wsgi.py

__init__

Một tệp trống cho phép Python biết rằng thư mục myproject là một gói Python, còn các tệp .py trong thư mục này là các mô-đun.

settings.py

Mô-đun này chứa tất cả các cài đặt cho toàn dự án.

urls.py

Mô-đun này chứa các ánh xạ URL toàn cục.

asgi.pywsgi.py

Các tệp này được các máy chủ ASGI hoặc WSGI sử dụng để giao tiếp với dự án Django của bạn khi triển khai nó lên những máy chủ này. Bạn thường không phải chỉnh sửa những tệp này và chúng không được sử dụng trong quá trình phát triển ứng dụng hàng ngày.

Django Dev Server

Bạn đã khởi động máy chủ phát triển của Django trong bài tập 1.01. Nó là một máy chủ web chỉ chạy trên máy tính cục bộ và chỉ dùng trong quá trình phát triển ứng dụng. Nó không được sử dụng khi triển khai ứng dụng ra thực tế.

Theo mặc định máy chủ Django Web Server lắng nghe trên công 8000 trên localhost (có địa chỉ IP là 127.0.0.1), nhưng điều này có thể thay đổi bằng cách thêm số cổng hoặc địa chỉ IP và số cổng sau đối số runserver:

$ python3 manage.py runserver 8001
Code language: Bash (bash)

Nó khiến máy chủ giờ lắng nghe trên cổng 8001 trên localhost (địa chỉ 127.0.0.1).

Bạn có thể yêu cầu nó lắng nghe trên một địa chỉ cụ thể nếu máy tính của bạn có nhiều hơn một địa chỉ, hoặc 0.0.0.0 nếu muốn lắng nghe trên mọi địa chỉ:

$ python3 manage.py runserver 0.0.0.0:8000
Code language: Bash (bash)

Django Dev Server tự động theo dõi dự án Django của bạn và khởi động lại tự động mỗi khi có sự thay đổi nào đó đối với dự án. Nhưng bạn vẫn phải làm mới trình duyệt để xem được các thay đổi.

Khi bạn muốn dừng Django Dev Server thì khi ở trong Terminal/Command Prompt hãy bấm tổ hợp phím Ctrl + C.

Ứng dụng Django

Một ứng dụng chứa tất cả các model, view và template… cần để ứng dụng hoạt động. Một dự án Django cần chứa ít nhất một ứng dụng. Nếu được thiết kế tốt, một ứng dụng trong dự án có thể bị xóa hoặc chuyển sang một dự án khác mà không cần sửa đổi. Thông thường mỗi một tài nguyên sẽ tương ứng với một ứng dụng.

Ứng dụng của bạn có thể có bất cứ tên nào miễn nó là tên Python hợp lệ (nghĩa là chỉ sử dụng chữ cái, chữ số và dấu gạch dưới) và không xung đột với các gói khác trong dự án. Để tạo ứng dụng, sử dụng lệnh quản lý startapp do manage.py cung cấp. Tập lệnh manage.py như ta đã biết phải được chạy qua lệnh python3 hoặc python. Ví dụ:

$ python3 manage.py startapp myapp
Code language: Bash (bash)

Lệnh startapp tạo một thư mục trong dự án cùng tên với tên ứng dụng. Bên trong thư mục ứng dụng là một số tệp và thư mục sau:

__init__.py admin.py apps.py migrations models.py tests.py views.py
Code language: CSS (css)

__init__.py

Tệp trống chỉ ra rằng thư mục này là một gói Python và các tệp .py trong nó là các mô-đun.

admin.py

Django có sẵn một trang quản trị dự án (Django Admin), dùng để xem và chỉnh sửa dữ liệu với giao diện đồ họa dễ sử dụng. Trong tệp này, bạn sẽ xác định cách các model của ứng dụng được hiển thị trong Django Admin.

apps.py

Mô-đun này chứa một số cấu hình cho siêu dữ liệu của ứng dụng. Bạn không cần chỉnh sửa tệp này.

models.py

Nơi mà bạn sẽ định nghĩa các model của ứng dụng.

migrations

Thư mục chứa các migration. Django sử dụng các tệp migration để ghi lại các thay đổi đối với cơ sở dữ liệu khi model bị thay đổi. Chúng được tạo ra bởi Django khi bạn chạy lệnh manage.py makemigrations và được lưu trữ trong thư mục này. Các thay đổi này chưa được áp dụng cho cơ sở dữ liệu cho đến khi chạy lệnh manage.py migrate.

tests.py

Nơi bạn sẽ viết các bài kiểm tra sự hoạt động của ứng dụng.

views.py

Nơi bạn sẽ viết các view của ứng dụng.

Chi tiết về view

View là một hàm nhận đối số là đối tượng HttpRequest (được tạo và truyền vào tự động bởi Django) và trả về một đối tượng HttpResponse.

Trong phần này, chúng ta sẽ viết các view dạng hàm, nhưng Django cũng hỗ trợ các view dạng lớp. View dạng lớp cho phép bạn sử dụng các mô hình của lập trình hướng đối tượng (chẳng hạn như thừa kế). Điều này cho phép bạn đơn giản hóa mã được sử dụng trong nhiều view có cùng một lôgic. View dạng lớp mạnh mẽ hơn nhưng cũng khó học hơn, chúng sẽ được giới thiệu sau khi bạn đã có kinh nghiệm với Django.

Đối tượng HttpRequest được chuyển tới view chứa tất cả các dữ liệu của HTTP request với các thuộc tính cơ bản sau:

  • method: trả về chuỗi là phương thức của HTTP request.
  • GET: đối tượng QueryDict chứa các tham số trong querystring – một phần của URL đứng sau dấu hỏi ? (nếu có).
  • POST: đối tượng QueryDict chứa các tham số trong phần thân của một request có phương thức POST.
  • headers: một từ điện Python chứa các header của request, khóa là tên của header (không phân biệt chữ hoa chữ thường) còn giá trị cũng chính là giá trị của header.
  • path: đường dẫn của HTTP request.

Ánh xạ URL

Django không biết view nào sẽ được gọi khi nhận một URL cụ thể. Vai trò của việc ánh xạ URL là xây dựng liên két giữa một URL và một view.

Ánh xạ URL tới view được định nghĩa trong tệp urls.py bên trong thư mục bookr (chứa settings.py).

Tệp này chứa một biến urlpatterns, là danh sách các đường dẫn mà Django kiểm tra lần lượt. Việc kiểm tra sẽ dừng lại khi Django tìm thấy đường dẫn phù hợp với URL của request.. Sau đó Django sẽ gọi hàm view hoặc một tệp urls.py khác tương ứng với đường dẫn này. Các tệp urls.py có liên kết với nhau dài bao nhiêu cũng được. Bằng cách này bạn có thể phân chia việc ánh xạ URL thành nhiều tệp urls.py riêng biệt để chúng không trở nên quá lớn. Sau một chuỗi các urls.py thì cuối cùng một view sẽ được gọi bởi Django và Django tự động truyền cho view này đối tượng HttpRequest biểu diễn HTTP Request và đồng thời cũng truyền các tham số được phân tích từ URL vào view.

Các quy tắc ánh xạ được tạo bằng cách gọi hàm path(), hàm này nhận một đường dẫn là đối số đầu tiên, đối số thứ hai là view hoặc một tệp urls.py khác.

Ngoài ra còn có hàm re_path(), tương tự path() ngoại trừ nó sử dụng một biểu thức chính quy làm đối số đầu tiên.

Để minh họa khái niệm này, ta dùng đoạn mã sau, là nội dung mặc định của tệp urls.py mà Django tạo ra:

from django.contrib import admin from django.urls import path urlpatterns = [ path('amdin/', admin.site.urls), ]
Code language: Python (python)

Hiện tại chỉ có một ánh xạ được thiết lập, ánh xạ bất kỳ URL có đường dẫn là admin/ tới mô-đun admin.site.urls chứa các ánh xạ URL của Django Admin. Đây không phải là ánh xạ tới một view, nó là ví dụ về việc kết hợp nhiều urls.py với nhau.

Bài tập 1.02: Viết một view và ánh xạ URL tới nó

View đầu tiên của chúng ta sẽ rất đơn giản trả về một văn bản tĩnh. Trong bài tâp này, chúng ta sẽ xem cách viết một view và cách ánh xạ một URL tới view này.

1. Mở reviews/views.py bạn sẽ thấy nội dung mặc định của nó như sau:

from django.shortcuts import render # Create your views here.
Code language: Python (python)

2. Xóa các mã mặc định trên và chèn lại nội dung sau:

from django.http import HttpResponse def index(request): return HttpResponse("Hello, world!")
Code language: Python (python)

3. Thiết lập một ánh xạ giữa URL và view index ta vừa tạo. Mở bookr/urls.py và sửa lại nội dung của nó thành:

from django.contrib import admin from django.urls import path import reviews.views urlpatterns = [ path('admin/', admin.site.urls), path('', reviews.views.index) ]
Code language: Python (python)

4. Quay lại trình duyệt của bạn và làm mới nó. Màn hình chào mừng mặc định của Django được thay thế bằng văn bản được định nghĩa trong view là Hello, world!:

Kết quả trả về bởi view

Thuộc tính GET, POST và đối tượng QueryDict

Dữ liệu có thể truyền đến máy chủ thông qua querystring hoặc phân thân của HTTP Request có phương thức POST. Bạn có thể nhận thấy các tham số trong querystring khi duyệt web – là chuỗi văn bản đặt sau dấu hỏi ? trong URL, – ví dụ: http://www.example.com/?parameter1=value1&parameter2=value2. Chúng ta cũng đã thấy trước đây một ví dụ về dữ liệu gửi từ form thông qua phần thân của một POST request: username=user1&password=password1.

Django tự động phân tích chuỗi querystring và phần thân của POST request thành các đối tượng QueryDict và lần lượt gắn nó cho HttpRequest.GETHttpRequest.POST.

Đối tượng QueryDict hoạt động giống như từ điển Python, ngoại trừ một khóa có thể chứa nhiều giá trị.

Ta sẽ minh họa cách hoạt động của QueryDict thông qua Django Shell (khởi động bằng cách chạy lệnh manage.py shell).

Đầu tiên qd được xây dừng từ một chuỗi chứa các tham số:

>>> qd = QueryDict("k=a&k=b&k=c")
Code language: Python (python)

Khi truy cập các khóa thông qua dấu ngoặc vuông hoặc phương thức .get(), giá trị cuối cùng sẽ được trả về:

>>> qd["k"] 'c' >>> qd.get("k") 'c'
Code language: Python (python)

Để lấy ra tất cả các giá trị của một khóa, sử dụng phương thức .getlist():

>>> qd.getlist("k") ['a', 'b', 'c']
Code language: Python (python)

Nếu khóa không tồn tại .getlist() trả về danh sách trống:

>>> qd.getlist("bad key") []
Code language: Python (python)

Truy cập một khóa không tồn tại bằng dấu ngoặc vuông sẽ gây ra lỗi KeyError, truy cập một khóa không tồn tại bằng .get() trả về None.

Đối tượng QueryDict là bất biến, muốn thay đổi cần tạo ra bản sao bằng phương thức .copy():

>>> qd["k"] = "d" AttributeError: This QueryDict instance is immutable >>> qd2 = qd.copy() >>> qd2 <QueryDict: {'k': ['a', 'b', 'c']}> >>> qd2["k"] = "d" >>> qd2["k"] "d"
Code language: Python (python)

Giờ hãy tưởng tượng có một URL: http://127.0.0.1:8000?val1=a&val2=b&val2=c&val3.

Đằng sau hậu trường, Django chuyển chuỗi querystring từ URL đến hàm khởi tạo QueryDict() và đính kèm nó vào request.GET và truyền đối tượng request vào view, giống như sau:

request.GET = QueryDict("val1=a&val2=b&val2=c&val3")
Code language: Python (python)

Trong view, chúng ta có thể truy cập các tham số này:

request.GET["val1"]
Code language: Python (python)

Giá trị trả về là a.

request.GET["val2"]
Code language: Python (python)

Bạn sẽ nhận được giá trị cuối cùng là c.

request.GET.getlist("val2")
Code language: Python (python)

Danh sách ["b", "c"] được trả về.

request.GET["val3"]
Code language: Python (python)

Khóa này nằm trong querystring nhưng không có giá trị nào được đặt, vì vậy giá trị trả về là một chuỗi trống.

request.GET["val4"]
Code language: Python (python)

Khóa này không tồn tại vì vậy lỗi KeyError xuất hiện. Sử dụng request.GET.get("val") sẽ không gây ra lỗi này, mà trả về None.

request.GET.getlist("val4")
Code language: Python (python)

Danh sách trống [] được trả về.

Bài tập 1.03: Khám phá thuộc tính GETQueryDict

Bây giờ chúng ta sẽ thực hiện một số thay đổi đối với view index của chúng ta từ bài tập trước để đọc các tham số từ URL được chứa bên trong thuộc tính GET của request, sau đó chúng ta sẽ thử nghiệm truyền các tham số khác nhau để xem kết quả:

1. Mở views.py, thêm một biến mới gọi là name sẽ dùng để lưu tham số name trong chuỗi querystring trong URL. Thêm dòng sau sau định nghĩa hàm index:

name = request.GET.get("name") or "world"
Code language: Python (python)

2. Thay đổi giá trị trả về để name được sử dụng như một phần của nội dung được trả về:

return HttpResponse("Hello, {}!".format(name))
Code language: Python (python)

Kết quả cuối cùng của views.py đạt được như sau:

from django.http import HttpResponse def index(request): name = request.GET.get("name") or "world" return HttpResponse("Hello, {}!".format(name))
Code language: Python (python)

3. Truy cập http://127.0.0.1:8000 trong trình duyệt của bạn. Bạn sẽ thấy rằng trang vẫn nói Hello, world!. Điều này là do ta chưa cung cấp tham số name. Bạn có thể thêm tên mình vào URL, chẳng hạn: http://127.0.0.1:8000?name=Ben:

Trang nhận được khi name=Ben

4. Thử thêm hai tên, chẳng hạn http://127.0.0.1:8000?name=Ben&name=John. Như chúng ta đã đề cập, giá trị cuối cùng của tham số được trả về, vì vậy bạn sẽ thấy Hello, John!

Trang nhận được khi name=Ben&name=John

5. Hãy thử không đặt giá trị cho name. Tải lại trang bạn sẽ thấy nó hiển thị Hello, world!

Khám phá các cài đặt của Python

Django lưu các cài đặt cho dự án trong tệp settings.py. Chúng ta sẽ thảo luận về một số cài đặt quan trọng nhất trong settings.py, những cài đặt khác sẽ được đề cập đến khi bạn thông thạo hơn với Django. Bạn nên mở settings.py và theo dõi để xem những cài đặt nằm ở đâu và giá trị của nó là gì với dự án của bạn.

Mỗi cài đặt là một biến toàn cục của settings.py. Thư tự mà chúng ta thảo luận giống thứ tự mà chúng xuất hiện trong tệp này mặc dù ta có thể bỏ qua các cài đặt ở giữa – ví dụ có cài đặt ALLOWED_HOST giữa DEBUGINSTALLED_APPS, mà ta không đề cập đến:

SECRET_KEY '...'
Code language: Python (python)

Đây là giá trị được tự động tạo ra, bạn không nên chia sẻ nó với bất kỳ ai. Nó được sử dụng để băm, tạo các token và dùng cho cac chức năng mã hóa khác.

DEBUG = True
Code language: Python (python)

Nếu giá trị này được đặt thành True, Django sẽ tự động hiển thị các lỗi ngay trên trình duyệt để cho bạn gỡ lỗi một cách dễ dàng hơn. Nó phải đặt thành False khi triển khai ứng dụng trên máy chủ thực sự.

INSTALLED_APPS = [...]
Code language: Python (python)

Khi bạn viết các ứng dụng Django riêng của mình (chẳng hạn như reviews) hoặc cài đặt một ứng dụng từ bên thứ ba, chúng nên được thêm vào danh sách này để Django có thể tự động tìm các template, các tập tĩnh, và các migration của ứng dụng.

ROOT_URLCONF = 'bookr.urls'
Code language: Python (python)

Đây là tệp urls.py đầu tiên được sử dụng trong chuỗi urls.py định nghĩa các ánh xạ URL tới view.

TEMPLATES = [...]
Code language: Python (python)

Có nhiều mục trong cài đặt này, hiện tại cái ta cần quan tâm là dòng mục:

'APP_DIRS': True,
Code language: Python (python)

Nó cho Django biết rằng sẽ tìm các template trong thư mục template bên trong mỗi ứng dụng đã được liệt kê trong INSTALLED_APPS khi cần render dữ liệu. Chúng ta hiện tại không có thư mục template nào trong thư mục reviews nhưng sẽ bổ sung trong bài tập tiếp theo.

Django có sẵn nhiều cài đặt không được liệt kê trong settings.py, Django sẽ sử dụng giá trị mặc định của những cài đặt này. Các ứng dụng của bên thứ ba cũng có thể bổ sung các cài đặt của riêng nó vào đây.

Truy xuất đến các cài đặt trong mã

Đôi khi bạn cần tham chiếu đến các cài đặt trong settings.py trong mã của mình. Bạn thường bị cám dỗ viết như sau:

from bookr import settings if settings.DEBUG: do_some_logging()
Code language: Python (python)

Cách này hoạt động, nhưng không tốt vì:

  • Bạn có thể chạy và sử dụng một tệp khác làm tệp cài đặt thay vì settings.py, do đó mã trên sẽ gây ra lỗi vì nó không thể tìm thấy settings.py. Trong trường hợp settings.py vẫn tồn tại, quá trình nạp thành công nhưng sẽ chứa những cài đặt không đúng.
  • Các cài đặt không được liệt kê trong settings.py được xem như không tồn tại và gây ra lỗi
  • Thư viện của bên thứ ba có thể thay đổi cách các cài đặt của bạn được định nghĩa, vì vậy settiengs.py sẽ trông hoàn toàn khác.

Cách tốt hơn là sử dụng mô-đun django.conf như sau:

from django.conf import settings if settings.DEBUG: do_some_logging();
Code language: Python (python)

Bài tập 1.04: Tạo thư mục template và tạo template cơ sở

Trong bài tập này, bạn sẽ tạo thư mục template cho ứng dụng reviews. Sau đó, bạn sẽ tạo một template cơ sở mà Django sử dụng để render dữ liệu và gửi kết quả qua một HTTP response.

1. Chúng ta đã thảo luận về settings.py và cài đặt INSTALLED_APPS của nó trong phần trên. Chúng ta cần thêm ứng dụng reviews vào INSTALLED_APPS để Django có thể tìm thấy các template của ứng dụng này. Mở settings.py cập nhật INSTALLED_APPS và thêm reviews vào cuối. Nó sẽ trông giống thế này:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'reviews', # thêm ứng dụng reviews ]
Code language: Python (python)

2. Tạo thư mục template trong thư mục reviews.

3. Tạo một template có tên base.html trong thư mục template vừa tạo ở trên, nội dung của nó như sau:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> Hello from a template! </body> </html>
Code language: HTML, XML (xml)

Bài tập 1.05: Render template trong view

Bây giờ, ta đã tạo một template, nhưng chúng ta cần cập nhật view index để nó hiển thị template này thay vì trả về Hello, (name)! đơn giản. Chúng ta thực hiện bằng cách dùng hàm render().

Hàm render() là một hàm tắt (thực hiện nhanh một thao tác nào đó) trả về một đối tượng HttpResponse. Nó chấp nhận ít nhất hai đối số, đối số đầu tiên là đối tượng request đã được truyền vào view và đối số thứ hai là tên hoặc đường dẫn tương đối (so với thư mục template) của template dùng để render. Đối số thứ ba (không bắt buộc) là một context (ngữ cảnh) chứa tất cả các biến mà template có thể sử dụng.

Trong bài tập này, bạn sẽ cập nhật lại hàm view index để render template base.html đã tạo trong bài tập trước. Bạn sẽ thực hiện nó bằng hàm render(), hàm này nạp template base.html từ ổ đĩa, render nó và trả kết quả về trình duyệt.

1. Mở views.py trong thư mục reviews và sửa lại nội dung thành:

from django.shortcuts import render def index(request): return render(request, "base.html")
Code language: Python (python)

2. Khởi động Django Dev Server nếu nó chưa chạy. Sau đó mở trình duyệt của bạn và làm mới địa chỉ http://127.0.0.1:8000. Bạn sẽ thấy Hello from a template! được hiển thị.

Kết quả render từ base.html

Bài tập 1.06: Sử dụng biến trong template

Các template không chỉ là tệp HTML tĩnh. Hầu hết thời gian, chúng sẽ chứa các biến được sẽ nội suy trong quá trình render. Các biến này được truyền từ view xuống template thông qua context – một từ điển chứa các tên biến và giá trị của chúng mà template có thể sử dụng.

Bên trong template, các biến được đặt giữa cặp hai dấu ngoặc nhọn, ví dụ {{ book_name }}. Nếu biến book_name không có trong context, Django sẽ không hiển thị gì tại vị trí đó.

1. Mở base.html và cập nhật lại nó để sử dụng một biến có tên name:

<body> Hello, {{ name }}! </body>
Code language: HTML, XML (xml)

2. Quay lại trình duyệt của bạn và làm mới (vẫn với địa chỉ http://127.0.0.1:8000). Bạn sẽ thấy trang web hiển thị Hello, ! bởi vì name hiện tại không tồn tại trong template.

3. Mở views.py và thêm một biến name với giá trị "world" bên trong index:

def index(request): name = "world" return render(request, "base.html")
Code language: Python (python)

Kết quả không thay đổi vì bạn chưa truyền biến name vào trong context. Ta truyền một context chứa biến name và giá trị bằng giá trị của name trong index thông qua hàm render như sau:

def index(request): name = "world" return render(request, "base.html", {"name": name})
Code language: Python (python)

4. Làm mới trình duyệt một lần nữa và bạn sẽ thấy nó bây giờ nói Hello, world!.

Kết quả khi render biến name trong base.html

Hoạt động 1.01: Tạo trang chủ

  1. Trong view index, render template base.html.
  2. Cập nhật template base.html và thêm một thông báo chào mừng. Nó nên xuất hiện trong cả thẻ <title và thẻ <h1> trong <body>.

Sau khi hoàn thành, trang chủ của bạn phải trông như sau:

Kết quả của hoạt động 1.01

Lời giải bước 1:

from django.shortcuts import render def index(request): return render(request, "base.html")
Code language: Python (python)

Lời giải bước 2:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Welcome to Bookr</title> </head> <body> <h1>Welcome to Bookr</h1> </body> </html>
Code language: HTML, XML (xml)

Hoạt động 1.02: Tạo trang tìm kiếm

Một tính năng hũu ích cho mọi trang web là khả năng tìm kiếm thông tin trên trang web một cách nhanh chóng. Bookr sẽ triển khai tìm kiếm sách, để cho phép mọi người tìm một cuốn sách dựa theo tiêu đề của nó. Trong khi chúng ta chưa có bất kỳ cuốn sách nào để tìm, chúng ta vẫn có thể triển khai được một trang hiển thị từ khóa mà người dùng đã tìm kiếm. Người dùng sẽ nhập từ khóa như một phần của querystring trong URL.

  1. Tạo một template. Nó có một biến chứa từ khóa tìm kiếm được truyền qua context. Hiển thị biến này trong thẻ <title> và thẻ <h1>. Sử dụng thẻ <em> bọc quanh từ khóa để làm cho nó in nghiêng.
  2. Thêm một hàm view vào views.py. View này đọc chuỗi querystring và lấy ra tham số chứa từ khóa tìm kiếm (thông qua request.GET).
  3. Ánh xạ dường dẫn book-search/ cho view vừa viết ở trên.

Kết quả cuối cùng sẽ trông như sau:

Kết quả của hoạt động 1.02

Lời giải bước 1: Tạo tệp HTML mới trong thư mục templates tên là search-results.html. Sử dụng biến search_text trong thẻ <title><h1>:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Search Results for {{ search_text }}</title> </head> <body> <h1>Search Results for <em>{{ search_text }}</em></h1> </body> </html>
Code language: HTML, XML (xml)

Lời giải bước 2: Tạo hàm mới trong views.py gọi là book_search. Nó nên tạo tên biến search_text được cài đặt tới tham số search trong querystring:

def book_search(request): search_text = request.GET.get("search", "")
Code language: Python (python)

Nếu không có từ khóa search, giá trị mặc định là chuỗi trống.

Sau đó render template search_results.html với search_text trong context:

def book_search(request): search_text = request.GET.get("search", "") return render(request, "search-results.html", {"search_text": search_text})
Code language: Python (python)

Lời giải bước 3: Ánh xạ URL book-search/ tới view book_search() ở trên. Mở urls.py và thêm mục sau vào urlspatterns:

path('book-search/', reviews.views.book_search)
Code language: Python (python)