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ệ ManyToManyField trong Django với Through

Trong Django, mối quan hệ nhiều-nhiều cho phép nhiều hàng trong một bảng liên kết với nhiều hàng trong một bảng khác. Để thiết lập mối quan hệ này, thường sử dụng một bảng liên kết trung gian. Tuy nhiên, có những tình huống yêu cầu bổ sung các trường thông tin vào bảng liên kết này để lưu trữ thêm dữ liệu về mối quan hệ. Trong bài viết này, bạn sẽ học cách sử dụng tham số through trong ManyToManyField của Django để thêm các trường bổ sung vào mối quan hệ nhiều-nhiều, giúp bạn quản lý dữ liệu một cách chi tiết và hiệu quả 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.

Giới thiệu về ManyToManyField trong Django với Through

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. Để thiết lập mối quan hệ nhiều-nhiều, cơ sở dữ liệu quan hệ sử dụng một bảng thứ ba gọi là bảng liên kết và tạo ra hai mối quan hệ một-nhiều từ các bảng nguồn.

Thông thường, bảng liên kết chứa các giá trị id của các bảng nguồn để các hàng trong một bảng có thể liên quan đến các hàng trong bảng khác.

Đôi khi, bạn có thể muốn thêm các trường bổ sung vào bảng liên kết. Ví dụ, mỗi nhân viên có thể có nhiều công việc trong suốt sự nghiệp của họ.

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

Để theo dõi thời gian khi một nhân viên bắt đầu và kết thúc một công việc, bạn có thể thêm các trường begin_date end_date vào bảng liên kết.

Để làm điều đó trong Django, bạn sử dụng ManyToManyField với tham số through.

Ví dụ, sau đây cho thấy cách liên kết một nhân viên với nhiều công việc thông qua bảng assignments:

from django.db import models

class Employee(models.Model):
    # Các trường của Employee...

class Job(models.Model):
    title = models.CharField(max_length=255)
    employees = models.ManyToManyField(Employee, through='Assignment')

    def __str__(self):
        return self.title
#Bài viết này được đăng tại freetuts.net
class Assignment(models.Model):
    employee = models.ForeignKey(Employee, on_delete=models.CASCADE)
    position = models.ForeignKey(Job, on_delete=models.CASCADE)
    begin_date = models.DateField()
    end_date = models.DateField(default=date(9999, 12, 31))

Cách hoạt động:

  • Đầu tiên, định nghĩa mô hình Job, thêm thuộc tính employees sử dụng ManyToManyField và truyền Assignment làm tham số through.
  • Thứ hai, định nghĩa lớp Assignment có hai khóa ngoại, một liên kết đến mô hình Employee, và một liên kết đến mô hình Job. Cũng thêm các thuộc tính begin_date và end_date vào mô hình Assignment.
  • Chạy lệnh makemigrations để tạo các migrations mới:
python manage.py makemigrations

Đầu ra sẽ như sau:

Migrations for 'hr':
  hr\migrations\0005_assignment_job_assignment_job.py
    - Create model Assignment
    - Create model Job
    - Add field job to assignment

Và thực thi lệnh migrate để áp dụng các thay đổi vào cơ sở dữ liệu:

python manage.py migrate

Đầu ra sẽ như sau:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, hr, sessions
Running migrations:
  Applying hr.0005_assignment_job_assignment_job... OK

Phía sau, Django sẽ tạo các bảng hr_job hr_assignment trong cơ sở dữ liệu.

Django through in many to many png

Bảng hr_assignment là bảng liên kết. Ngoài các trường employee_id position_id, nó còn có các trường begin_date end_date.

Tạo dữ liệu mới trong Django

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

python manage.py shell_plus

Thứ hai, tạo ba công việc mới:

>>> j1 = Job(title='Software Engineer I')
>>> j1.save()
#Bài viết này được đăng tại freetuts.net
>>> j2 = Job(title='Software Engineer II') 
>>> j2.save() 
>>> j3 = Job(title='Software Engineer III')
>>> j3.save()
>>> Job.objects.all()
<QuerySet [<Job: Software Engineer I>, <Job: Software Engineer II>, <Job: Software Engineer III>]>

Tạo các thực thể cho models trung gian trong Django

Đầu tiên, tìm nhân viên có tên freetuts .net và .net freetuts:

>>> e1 = Employee.objects.filter(first_name='freetuts',last_name='.net').first()
>>> e1
<Employee: freetuts .net>
#Bài viết này được đăng tại freetuts.net
>>> e2 = Employee.objects.filter(first_name='.net', last_name='freetuts').first()
>>> e2
<Employee: .net freetuts>

Thứ hai, tạo các thực thể của mô hình trung gian (Assignment):

>>> from datetime import date
>>> a1 = Assignment(employee=e1,job=j1, begin_date=date(2019,1,1), end_date=date(2021,12,31))
>>> a1.save()
#Bài viết này được đăng tại freetuts.net
>>> a2 = Assignment(employee=e1,job=j2, begin_date=date(2022,1,1))
>>> a2.save()
>>> a3 = Assignment(employee=e2, job=j1, begin_date=date(2019, 3, 1))
>>> a3.save()

Tìm các nhân viên giữ vị trí Software Engineer I (j1):

>>> j1.employees.all()
<QuerySet [<Employee: freetuts .net>, <Employee: .net freetuts>]>

Phía sau, Django thực hiện truy vấn sau:

SELECT
  "hr_employee"."id",
  "hr_employee"."first_name",
  "hr_employee"."last_name",
  "hr_employee"."contact_id",
  "hr_employee"."department_id"
FROM "hr_employee"
#Bài viết này được đăng tại freetuts.net
INNER JOIN "hr_assignment"
  ON ("hr_employee"."id" = "hr_assignment"."employee_id")
WHERE "hr_assignment"."job_id" = 1

Tương tự, bạn có thể tìm tất cả nhân viên giữ vị trí Software Engineer II:

>>> j2.employees.all()
<QuerySet [<Employee: freetuts .net>]>

Xóa các thực thể của models trung gian trong Django

Đầu tiên, xóa .net freetuts (e2) khỏi công việc Software Engineer II bằng cách sử dụng phương thức remove():

>>> j2.employees.remove(e2) 

Thứ hai, xóa tất cả nhân viên khỏi công việc Software Engineer I bằng cách sử dụng phương thức clear():

>>> j1.employees.clear() 

Công việc j1 sẽ không có nhân viên nào nữa:

>>> j1.employees.all() 
<QuerySet []>

Kết bài

Việc sử dụng tham số through trong ManyToManyField của Django giúp bạn mở rộng khả năng lưu trữ và quản lý dữ liệu trong mối quan hệ nhiều-nhiều. Bạn có thể dễ dàng thêm các trường bổ sung vào bảng liên kết để lưu trữ thông tin chi tiết hơn về mối quan hệ giữa các bảng. Điều này không chỉ giúp cải thiện cấu trúc dữ liệu mà còn tăng tính linh hoạt và hiệu quả trong việc quản lý và truy vấn dữ liệu. Hy vọng hướng dẫn này đã cung cấp cho bạn những kiến thức cần thiết để áp dụng tham số through trong dự án Django của mình.

Cùng chuyên mục:

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn xây dựng Command-Line Interface (CLI) bằng Quo trong Python

Hướng dẫn toàn diện về module datetime trong Python

Hướng dẫn toàn diện về module datetime trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Cách truy cập và thiết lập biến môi trường trong Python

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Lớp dữ liệu (Data Classes) trong Python với decorator @dataclass

Từ khóa yield trong Python

Từ khóa yield trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sự khác biệt giữa sort() và sorted() trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Sử dụng Poetry để quản lý dependencies trong Python

Định dạng chuỗi Strings trong Python

Định dạng chuỗi Strings trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Một tác vụ phổ biến khi làm việc với danh sách trong Python

Làm việc với các biến môi trường trong Python

Làm việc với các biến môi trường trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa set() và frozenset() trong Python

Sự khác biệt giữa iterator và iterable trong Python

Sự khác biệt giữa iterator và iterable trong Python

Cách làm việc với file tarball/tar trong Python

Cách làm việc với file tarball/tar trong Python

Chuyển đổi kiểu dữ liệu trong Python

Chuyển đổi kiểu dữ liệu trong Python

Sự khác biệt giữa toán tử == và is trong Python

Sự khác biệt giữa toán tử == và is trong Python

Làm việc với file ZIP trong Python

Làm việc với file ZIP trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Cách sử dụng ThreadPoolExecutor trong Python

Sự khác biệt giữa byte objects và string trong Python

Sự khác biệt giữa byte objects và string trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format  trong Python

Xử lý độ chính xác các hàm floor, ceil, round, trunc, format trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Cách lặp qua nhiều list với hàm zip() trong Python

Top