Django(3) - Mô hình MVT

Bài trước: Django(2) - Tạo ứng dụng đầu tiên

-----

1         Mô hình MVT



Đọc thêm: https://data-flair.training/blogs/django-mtv-architecture/

Mô hình MVT là biến thể của mô hình MVC. MVT là viết tắt của Model-View-Template. Về bản chất MVT và MVC đều giống nhau, đều chia ứng dụng ra thành ba thành phần: phần xử lý logic, phần hiển thị và phần thao tác với cơ sở dữ liệu.

Sự khác biệt của mô hình MVT và MVC được minh họa trong bảng sau:

Mô hình MVC

Mô hình MVT

Chức năng

Model

Model

Làm việc với cơ sở dữ liệu

View

Template

Hiển thị giao diện

Controller

View

Xử lý logic

1.1       Template

Template nghĩa là bản mẫu, là công cụ để tạo ra các giao diện web. Trong một bản mẫu sẽ có những phần cố định (static) và những phần được bổ sung sau (dynamic).

Django có hai công cụ để tạo các template là DTL và Jinja2.

Để tạo ra các template, bạn sẽ sử dụng cú pháp của một trong hai công cụ là DTL hoặc Jinja2, sau đó chuyển template cho template engine để chuyển sang mã HTML.

Như đã biết Template trong Django có vai trò như View trong mô hình MVC, phụ trách việc hiển thị nội dung.

Phân tích một tình huống cụ thể để hiểu về hoạt động của template. Hình sau là một bố cục phổ biến của trang web:


Ở bố cục trên, các vùng Top Navigation, Header, Footer thường là không đổi giữa các trang trong một website; vùng Side Navigation và Page Content chính là nội dung riêng biệt của mỗi trang. Vậy,

– Vùng tĩnh gồm: Top Navigation, Header, Footer (viết trong tập tin base.html)

– Vùng động gồm: Side Navigation và Page Content (viết trong các trang riêng biệt, ví dụ trang home.html)

Cú pháp của Jinja2 gồm bốn thành phần:

– Variables (biến)

– Tags (thẻ)

– Filters (bộ lọc)

– Comments (chú thích)

Biến

Biến được sử dụng để chèn dữ liệu động trong một template. Cú pháp sử dụng biến {{ tên_biến}}. Biến làm việc theo kiểu key:value, nghĩa là khi thực thi template, giá trị của biến (value) sẽ thay thế cho tên_biến (key).

Ví dụ:

Họ của tôi là {ho} và tên của tôi là {ten}

Với ho : Nguyễn, ten : Tèo. Kết quả chạy template sẽ có kết quả là

Họ của tôi là Nguyễn và tên của tôi là Tèo.

Thẻ

Thẻ được sử dụng để thể hiện một số xử lý logic trong quá trình kết xuất từ template ra trang kết quả (HTML).

Ví dụ: một thẻ có thể xuất ra nội dung (content), cấu trúc điều khiển.

Bạn có thể sử dụng thẻ để thực hiện lệnh if, for, lấy dữ liệu từ cơ sở dữ liệu.

Thẻ được bao bằng cặp dấu {%  %}.

Ví dụ:

<title>{% block title %}{% endblock %}</title>

Thẻ block nói cho template engine biết là các template con có thể ghi đè nội dung vào vùng này. Cụ thể title của trang con có thể ghi đè vào title của trang cha (base).

1.2       Áp dụng template vào dự án

Trong web app, tạo thư mục templates, trong thư mục templates tạo thư mục pages để chứa các template, trong pages tạo tập tin base.html.

[base.html]

<!doctype html>

<html>

<head>

    <title>{% block title %}{% endblock %}</title>

</head>

<body>

    Nội dung

    {% block content %}

    {% endblock %}

</body>

</html>

Tạo trang home.html dựa trên trang base.html.

[home.html]

{% extends "pages/base.html" %}

{% block title %}Home{% endblock %}

{% block content %}

    <p>Chào bác tèo.</p>

    <p>Đây là trang app home.</p>

{% endblock %}

Trang base.html chính là cái khung cơ bản của trang web, chứa các vùng không thay đổi giữa các trang.

Trang home.html là nội dung riêng biệt của trang home.

Template được thiết kế theo nguyên tắc không lặp lại (DRY: Don’t Repeat Yourself), nó sẽ viết những phần chung vào trang base.html, sau đó ghép các trang riêng biệt với trang base.html để tạo ra trang kết quả. Hay nói cách khác, các trang riêng biệt sẽ kế thừa từ trang base.html. Xem hình minh họa:



Đọc thêm về base template tại đây: https://jinja.palletsprojects.com/en/2.11.x/templates/

Xem thêm clip 4 (template và jinja) của HowKteam: https://www.youtube.com/watch?v=p1q39gPvDAI&list=PL33lvabfss1z8GYxjyMulCnhcYGk5ah8P&index=4

1.3       Bootstrap trong Django

Trong thư mục home (web app), tạo thư mục tên là static để chứa bootstrap.

Tải bootstrap từ trên mạng (ví dụ chọn phiên bản 4), giải nén và chép hai thư mục css và js vào static.

Tạo giao diện mẫu cho một blog trong tập tin base.html.

Trong base.html, sử dụng thẻ {% load static %} để lấy đường dẫn của thư mục static lưu vào nhãn static.

Ví dụ:

 {% load static %}

Sử dụng,

<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css">

Đọc thêm về staticfiles: https://django.readthedocs.io/en/stable/howto/static-files/index.html

[base.html]

<!doctype html>

<html>

<head>

    {% load static %}

    <title>{% block title %}{% endblock %}</title>

    <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}" type="text/css">

</head>

<body>

    <div class="container">

        <div class="row">

            <div class="col-sm-2">

                <img src="{% static 'images/goldfish.png' %}" class="responsive-img" style="max-height:50px">

            </div>

            <div class="col-sm-10">

                <h1>My blog</h1>

            </div>

        </div>

    </div>

    {% block content %}

    {% endblock %}

</body>

</html>

Đọc thêm về Bootstrap để tạo ra các trang theo yêu cầu.

1.4       Liên kết trang trong Template

Như đã biết, các định tuyến URL trong project/urls.py thực hiện ở mức web app, ví dụ path('home/', include('home.urls')) sau đó, các định tuyến URL chi tiết hơn sẽ được tạo trong web app/urls.py. Ví dụ: path('', views.index)

[home/urls.py]

from django.urls import path

from . import views

 

urlpatterns = [

    path('', views.index)

]

Ở đoạn mã trên, định tuyến trong web app/urls.py đã dẫn tới tập tin views, với hàm mặc định được gọi là index().

[views.py]

from django.shortcuts import render

from django.http import HttpResponse 

 

def index(request):

    return render(request, "pages/home.html")

Trong tập tin views.py, cho thấy nếu hàm index() được gọi thì sẽ hiển thị trang “pages/home.html”.

Nếu muốn thêm một định tuyến mới, thì cần chỉnh sửa ở hai tập tin là app/urls.py và views.py.

Ví dụ để thêm trang contact.html, cần thêm đoạn mã sau:

[home/urls.py]

from django.urls import path

from . import views

 

urlpatterns = [

    path('', views.index),

    path('contact/', views.contact)

]

[views.py]

from django.shortcuts import render

from django.http import HttpResponse 

 

def index(request):

    return render(request, "pages/home.html")

def contact(request):

    return render(request, "pages/contact.html")

Có thể điều chỉnh để khi người dùng nhập tên miền trang web thì vào thẳng trang home.html ở tập tin project/urls.py.

Ví dụ,

urlpatterns = [

    path('admin/', admin.site.urls),

    path('', include('home.urls')),

    path('listItems/', include('listItems.urls'))

]

Xem thêm clip 5 và 6 (sử dụng bootstrap) của HowKteam:

https://www.youtube.com/watch?v=_D5WGp2chtk&list=PL33lvabfss1z8GYxjyMulCnhcYGk5ah8P&index=5

https://www.youtube.com/watch?v=TzWwzM0SBRk&list=PL33lvabfss1z8GYxjyMulCnhcYGk5ah8P&index=6

-----

Cập nhật: 28/4/2021

Bài sau: Django (4) - Làm việc với cơ sở dữ liệu

-----

Bạn muốn tự học HTML bài bản? Xem thêm

OOP trong PHP (1) - Class, object, constructor, destructor

1         OOP trong PHP

OOP là viết tắt của object oriented programming, là một phương pháp lập trình được sử dụng phổ biến.

Chương trình được viết theo phương pháp hướng đối tượng có tính tiến hóa, dễ mở rộng, dễ bảo trì và mã nguồn có tính tái sử dụng cao.

Một số kiến thức quan trọng cần tìm hiểu về phương pháp lập trình hướng đối tượng gồm:

– Làm sao để tạo lớp (class), tạo đối tượng (object)

– Tính đóng gói (encapsulation), hay che dấu dữ liệu (data hiding)

– Tính kế thừa (inheritance)

– Tính đa hình (polymorphism)

1.1       Làm sao để tạo lớp, tạo đối tượng

Đối tượng (object) là các thực thể trong thế giới thực (ví dụ: máy tính, sinh viên), hoặc là các khái niệm trừu tượng (ví dụ: tập tin, dữ liệu) cần biểu diễn (sử dụng) trong phần mềm.

Các đối tượng có đặc điểm giống nhau được xếp vào một nhóm hay một lớp (class). Ví dụ: lớp đối tượng SinhVien gồm các bạn đang học tại một trường cao đẳng/đại học, đối tượng TapTin gồm các đoạn dữ liệu được lưu trên đĩa.

Trong lập trình hướng đối tượng, người ta thường sử dụng từ khóa class để định nghĩa các đặc điểm và hành động chung của một lớp các đối tượng.

Một đối tượng sẽ là một đại diện cụ thể của một lớp đối tượng, ví dụ sinh viên Nguyễn Văn Tèo là một đại diện của lớp SinhVien. Cũng có thể gọi một đối tượng là một thể hiện (instance) của một lớp.

Công việc của lập trình viên là tạo ra các class trước, sau đó tạo ra các object từ các class đã có.

Tạo ra class là việc liệt kê các thuộc tính (attribute hay property) cùng với các hành động (method hay operation hay function) của một lớp đối tượng cụ thể.

Ví dụ:

class SinhVien { // định nghĩa lớp đối tượng

        public $hoTen; // thuộc tính

        public $diem; // thuộc tính

 

        function chao() { // phương thức, hành động

            echo 'Chao cac ban';

        }

    }

    $sv = new SinhVien(); // tạo ra đối tượng sv thuộc lớp đối tượng SinhVien

    $sv->chao(); // gọi phương thức

//=> Chao cac ban

1.2       Hàm khởi tạo

Hầu hết các class đều có một phương thức (hàm) đặc biệt là hàm khởi tạo (hay tạo lập, constructor), hàm này không có kiểu trả về, có tên là __construct(), thực hiện khởi tạo các biến thành viên, được thực thi tự động khi tạo ra đối tượng.

Ví dụ,

 class SinhVien {

        public $hoTen;

        public $diem; 

 

        function __construct() {

            echo "Hàm khởi tạo được gọi";

        }

    }

    $sv = new SinhVien();

//=> Hàm khởi tạo được gọi

Ví dụ, truyền tham số cho hàm khởi tạo

 class SinhVien {

        public $hoTen;

        public $diem; 

 

        function __construct($thamSo) {

            echo "Tham so truyen cho ham khoi tao la: " . $thamSo;

        }

    }

    $sv = new SinhVien('123');

    //=> Tham so truyen cho ham khoi tao la: 123

 

1.3       Hàm hủy

Ngược lại với hàm khởi tạo là hàm hủy (phương thức hủy, destructor). Hàm hủy thực hiện một số chức năng trước khi object bị hủy.

Hàm hủy có tên là __destruct(), sẽ tự động chạy khi object bị hủy. Không thể truyền tham số cho hàm hủy.

Ví dụ một số thao tác trong hàm hủy: ghi dữ liệu vào cơ sở dữ liệu, xuất thẻ đóng </body></html> của một tài liệu HTML.

Ví dụ hàm hủy:

    class SinhVien {

        public $hoTen;

        public $diem; 

 

        function __construct() {

            echo "<html><body>";

        }

        

        function __destruct(){

            echo "</body></html>";

        }

    }

    $sv = new SinhVien();

    echo "Thong tin sinh vien";

//=> <html><body>Thong tin sinh vien</body></html>

Object bị hủy khi nào?

Trong PHP, mỗi giá trị đều được lưu trong cấu trúc dữ liệu tên là zval. Trong cấu trúc zval, ngoài trường cho biết kiểu dữ liệu, giá trị của dữ liệu, còn có một trường (refcount) cho biết đang có bao nhiêu biến tham chiếu tới giá trị đó (reference count). Trong trường hợp dữ liệu là object thì refcount cho biết có bao nhiêu tham chiếu tới object.

Ví dụ:

class SinhVien {

        public $hoTen;

        public $diem; 

 

        function __construct() {

            echo "Ham khoi tao <br>";

        }

        

        function __destruct(){

            echo "<br>Ham huy";

        }

    }

    $a = new SinhVien();

    debug_zval_dump($a); // refcount(2): $a và debug_zval_dump tham chiếu tới một thể hiện của SinhVien

    $b = $a;

    $c = $b;

    debug_zval_dump($a); // refcount(4): $a, $b, $c, $debug_zval_dump

    unset($a);

    debug_zval_dump($b); // refcount(3): $b, $c, $debug_zval_dump  

Refcount có giá trị bằng 0 trong ba trường hợp sau:

– Mỗi lần gọi hàm unset(object) sẽ làm giá trị của refcount đi một giá trị

– Kết thúc hàm có chứa object

– Kết thúc chương trình

Ví dụ dưới đây minh họa trường hợp: sau hàm unset($a), hàm hủy sẽ được gọi,

$a = new SinhVien();

    unset($a);

    echo "<br> sau ham huy";

<///// 01 – OOP trong PHP

-----

Cập nhật: 19/4/2021

Đọc thêm: