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:

Tìm hiểu Backreferences trong regex của Python

Tìm hiểu Backreferences trong regex của Python

Nhóm Non-capturing trong Regex Python

Nhóm Non-capturing trong Regex Python

Các nhóm Capturing trong regex của Python

Các nhóm Capturing trong regex của Python

Sets và Ranges trong Regex của Python

Sets và Ranges trong Regex của Python

Lượng từ non-greed trong Regex của Python

Lượng từ non-greed trong Regex của Python

Chế độ Greedy trong Regex Python

Chế độ Greedy trong Regex Python

Các lượng từ trong Regex của Python

Các lượng từ trong Regex của Python

Regex Word Boundary trong Python

Regex Word Boundary trong Python

Regex với các ký tự neo trong Python

Regex với các ký tự neo trong Python

Các tập ký tự trong Regex của Python

Các tập ký tự trong Regex của Python

Biểu thức chính quy (Regex) trong Python

Biểu thức chính quy (Regex) trong Python

Tìm hiểu Context Managers trong Python

Tìm hiểu Context Managers trong Python

Biểu thức Generator trong Python

Biểu thức Generator trong Python

Tìm hiểu Generators trong Python

Tìm hiểu Generators trong Python

Sử dụng hiệu quả hàm iter() trong Python

Sử dụng hiệu quả hàm iter() trong Python

Iterator vs Iterable trong Python

Iterator vs Iterable trong Python

Tìm hiểu về Iterator trong Python

Tìm hiểu về Iterator trong Python

Dãy số Fibonacci trong Python

Dãy số Fibonacci trong Python

Cắt Chuỗi (Slicing) trong Python

Cắt Chuỗi (Slicing) trong Python

Sự khác biệt giữa Tuple và List trong Python

Sự khác biệt giữa Tuple và List trong Python

Top