DJANGO
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Mối quan hệ Many-to-Many trong Django với Python

Một trong những mối quan hệ phổ biến mà bạn có thể gặp phải là mối quan hệ nhiều-nhiều (many-to-many). Trong bài viêt này, bạn sẽ học cách sử dụng ManyToManyField để mô hình hóa mối quan hệ nhiều-nhiều trong Django một cách hiệu quả. Mình sẽ được hướng dẫn từng bước, từ việc định nghĩa mô hình, tạo bảng liên kết trong cơ sở dữ liệu, cho đến cách truy vấn và quản lý dữ liệu liên quan. Bằng cách áp dụng các kỹ thuật này, bạn sẽ có thể xây dựng các ứng dụng Django mạnh mẽ và linh hoạt hơn.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Mối quan hệ Many-to-Many là gì?

Trong một mối quan hệ nhiều-nhiều, nhiều hàng trong một bảng có liên quan đến nhiều hàng trong một bảng khác.

Ví dụ, một nhân viên có thể tham gia nhiều chương trình đãi ngộ và một chương trình đãi ngộ có thể áp dụng cho nhiều nhân viên.

Do đó, nhiều hàng trong bảng nhân viên có liên quan đến nhiều hàng trong bảng chương trình đãi ngộ. Vì vậy, mối quan hệ giữa nhân viên và các chương trình đãi ngộ là một mối quan hệ nhiều-nhiều.

Bài viết này được đăng tại [free tuts .net]

Thông thường, các cơ sở dữ liệu quan hệ không triển khai trực tiếp mối quan hệ nhiều-nhiều giữa hai bảng. Thay vào đó, chúng sử dụng một bảng thứ ba, bảng liên kết, để thiết lập hai mối quan hệ một-nhiều giữa hai bảng và bảng liên kết.

Sơ đồ sau minh họa mối quan hệ nhiều-nhiều trong cơ sở dữ liệu giữa các bảng hr_employee hr_compensation:

Django many to many example png

Bảng hr_employee_compensations là một bảng liên kết. Nó có hai khóa ngoại là employee_id compensation_id.

Khóa ngoại employee_id tham chiếu đến id của bảng hr_employee và khóa ngoại compensation_id tham chiếu đến id trong bảng hr_compensation.

Thông thường, bạn không cần cột id trong bảng hr_employee_compensations làm khóa chính và sử dụng cả employee_id compensation_id làm khóa chính tổng hợp. Tuy nhiên, Django luôn tạo cột id làm khóa chính cho bảng liên kết.

Ngoài ra, Django tạo một ràng buộc duy nhất bao gồm các cột employee_id compensation_id. Nói cách khác, sẽ không có cặp giá trị employee_id compensation_id trùng lặp trong bảng hr_employee_compensations.

Để tạo mối quan hệ nhiều-nhiều trong Django, bạn sử dụng ManyToManyField. Ví dụ sau sử dụng ManyToManyField để tạo mối quan hệ nhiều-nhiều giữa các mô hình Employee và Compensation:

class Compensation(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name
#Bài viết này được đăng tại freetuts.net
class Employee(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    contact = models.OneToOneField(
        Contact,
        on_delete=models.CASCADE,
        null=True
    )

    department = models.ForeignKey(
        Department,
        on_delete=models.CASCADE
    )
#Bài viết này được đăng tại freetuts.net
    compensations = models.ManyToManyField(Compensation)

    def __str__(self):
        return f'{self.first_name} {self.last_name}'

Cách thức hoạt động

Đầu tiên, định nghĩa một lớp mô hình Compensation mới mở rộng từ lớp models.Model.

Thứ hai, thêm trường compensations vào lớp Employee. Trường compensations sử dụng ManyToManyField để thiết lập mối quan hệ nhiều-nhiều giữa các lớp Employee và Compensation.

Để lan truyền các thay đổi của các mô hình vào cơ sở dữ liệu, bạn chạy lệnh makemigrations:

python manage.py makemigrations

Nó sẽ hiển thị thông tin như sau:

Migrations for 'hr':
  hr\migrations\0004_compensation_employee_compensations.py
    - Create model Compensation
    - Add field compensations to employee

Và thực hiện lệnh migrate:

python manage.py migrate

Django tạo hai bảng mới là hr_compensation và một bảng liên kết hr_employee_compensations như sau:

Django many to many example 20 1  png

Tạo dữ liệu trong Django

Đầu tiên, chạy lệnh shell_plus:

python manage.py shell_plus

Thứ hai, tạo ba chương trình đãi ngộ bao gồm Cổ phiếu, Thưởng và Chia sẻ Lợi nhuận:

>>> c1 = Compensation(name='Stock')
>>> c1.save()
#Bài viết này được đăng tại freetuts.net
>>> c2 = Compensation(name='Bonuses')
>>> c2.save()
>>> c3 = Compensation(name='Profit Sharing')
>>> c3.save()
>>> Compensation.objects.all()
<QuerySet [<Compensation: Stock>, <Compensation: Bonuses>, <Compensation: Profit Sharing>]>

Lấy nhân viên có tên là freetuts và họ là .net:

>>> e = Employee.objects.filter(first_name='freetuts',last_name='.net').first()
>>> e
<Employee: freetut.net>

Thêm các chương trình đãi ngộ cho nhân viên

Đầu tiên, thêm .net freetuts vào các chương trình đãi ngộ cổ phiếu (c1) và thưởng (c2) sử dụng phương thức add() của thuộc tính compensations và phương thức save() của đối tượng Employee:

>>> e.compensations.add(c1)
>>> e.compensations.add(c2)
>>> e.save()

Thứ hai, truy cập tất cả các chương trình đãi ngộ của John Doe sử dụng phương thức all() của thuộc tính compensations:

>>> e.compensations.all()
<QuerySet [<Compensation: Stock>, <Compensation: Bonuses>]>

Rõ ràng trong kết quả, John Doe có hai chương trình đãi ngộ.

Thứ ba, thêm .net freetuts vào ba chương trình đãi ngộ bao gồm cổ phiếu, thưởng và chia sẻ lợi nhuận:

>>> e = Employee.objects.filter(first_name='Jane',last_name='Doe').first()
>>> e
<Employee: Jane Doe>
>>> e.compensations.add(c1)
>>> e.compensations.add(c2)
#Bài viết này được đăng tại freetuts.net
>>> e.compensations.add(c3)
>>> e.save()
>>> e.compensations.all()
<QuerySet [<Compensation: Stock>, <Compensation: Bonuses>, <Compensation: Profit Sharing>]>

Bên trong, Django đã chèn các id của nhân viên và các chương trình đãi ngộ vào bảng liên kết:

 id | employee_id | compensation_id
----+-------------+-----------------
  1 |           5 |               1
  2 |           5 |               2
  3 |           6 |               1
  4 |           6 |               2
  5 |           6 |               3
(5 rows)

ìm tất cả nhân viên đã tham gia chương trình cổ phiếu sử dụng thuộc tính employee_set của đối tượng Compensation:

>>> c1
<Compensation: Stock>
#Bài viết này được đăng tại freetuts.net
>>> c1.employee_set.all()
<QuerySet [<Employee: freetut.net>, <Employee: .net freetuts>]>

Nó trả về hai nhân viên như mong đợi.

Thứ năm, bạn có thể sử dụng thuộc tính employee_set để tìm tất cả nhân viên có chương trình chia sẻ lợi nhuận:

>>> c3
<Compensation: Profit Sharing>
>>> c3.employee_set.all()
#Bài viết này được đăng tại freetuts.net
<QuerySet [<Employee: .net freetuts>]>

Nó trả về một nhân viên.

Django cho phép bạn truy vấn qua mối quan hệ. Ví dụ, bạn có thể tìm tất cả nhân viên có chương trình đãi ngộ với id là 1:

>>> Employee.objects.filter(compensations__id=1)
<QuerySet [<Employee: freetuts .net>, <Employee: .net freetuts>]>

Hoặc với tên là "Profit Sharing":

>>> Employee.objects.filter(compensations__name="Profit Sharing")
<QuerySet [<Employee: .net freetuts>]>

Xóa chương trình đãi ngộ khỏi nhân viên

Để xóa một chương trình đãi ngộ khỏi nhân viên, bạn sử dụng phương thức remove() của thuộc tính compensations của đối tượng Employee. Ví dụ:

Đầu tiên, lấy nhân viên có tên là .net freetuts:

>>> e = Employee.objects.filter(first_name='.net',last_name='freetuts').first()
>>> e
<Employee: .net freetuts>

Thứ hai, xóa chương trình chia sẻ lợi nhuận (c3) khỏi .net freetuts và lưu thay đổi vào cơ sở dữ liệu:

>>> e.compensations.remove(c3)
>>> e.save()

Lấy tất cả các chương trình đãi ngộ của .net freetuts:

>>> e.compensations.all()
<QuerySet [<Compensation: Stock>, <Compensation: Bonuses>]>

Kết bài

Trong một mối quan hệ nhiều-nhiều, nhiều hàng trong một bảng có liên quan đến nhiều hàng trong một bảng khác. Các cơ sở dữ liệu quan hệ sử dụng bảng liên kết để thiết lập mối quan hệ nhiều-nhiều giữa hai bảng, cho phép quản lý và truy xuất dữ liệu một cách hiệu quả. Việc sử dụng ManyToManyField trong Django giúp bạn mô hình hóa một cách trực quan và dễ dàng các mối quan hệ phức tạp này giữa các mô hình. Bằng cách nắm vững cách thiết lập và quản lý mối quan hệ nhiều-nhiều, bạn có thể xây dựng các ứng dụng Django mạnh mẽ và linh hoạt, đáp ứng tốt các yêu cầu phức tạp của dự án.

Cùng chuyên mục:

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Cách thêm Progress Bar trong Python với chỉ một dòng Code

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Toán tử Walrus Operator- Tính năng mới trong Python 3.8

Cách nạp dữ liệu Machine Learning từ File trong Python

Cách nạp dữ liệu Machine Learning từ File trong Python

Hướng dẫn sử dụng Google Sheets API với Python

Hướng dẫn sử dụng Google Sheets API với Python

Xây dựng  web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng web Python tự động hóa Twitter | Flask, Heroku, Twitter API & Google Sheets API

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Xây dựng Web Machine Learning đẹp mắt với Streamlit và Scikit-learn trong Python

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

Hướng dẫn tạo Chatbot đơn giản bằng PyTorch

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

11 mẹo và thủ thuật để viết Code Python hiệu quả hơn

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn làm ứng dụng TODO với Flask dành cho người mới bắt đầu trong Python

Hướng dẫn viết Snake Game bằng Python

Hướng dẫn viết Snake Game bằng Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng chế độ interactive trong Python

Cách sử dụng Python Debugger với hàm breakpoint()

Cách sử dụng Python Debugger với hàm breakpoint()

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Xây dựng ứng dụng Web Style Transfer với PyTorch và Streamlit

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Cách cài đặt Jupyter Notebook trong môi trường Conda và thêm Kernel

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn xây dựng ứng dụng dự đoán giá cổ phiếu bằng Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hướng dẫn tạo ứng dụng AI hội thoại với NVIDIA Jarvis trong Python

Hỗ trợ Async trong Django 3.1

Hỗ trợ Async trong Django 3.1

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

8 mẹo tái cấu trúc Python giúp mã sạch hơn và Pythonic

Ý nghĩa của if __name__ ==

Ý nghĩa của if __name__ == "__main__" trong Python

Cách xóa phần tử trong danh sách Python

Cách xóa phần tử trong danh sách Python

Top