📜  Django 中的中间字段 | Python(1)

📅  最后修改于: 2023-12-03 15:14:43.765000             🧑  作者: Mango

Django 中的中间字段

在 Django 中,我们可以使用中间字段来处理在多个模型之间的多对多关系,以及关联表中存储其他数据的情况。

多对多关系
官方文档

在 Django 中,我们可以通过 ManyToManyField 字段来创建多对多的关系,如下所示:

class Model1(models.Model):
    field1 = models.CharField(max_length=100)

class Model2(models.Model):
    field2 = models.CharField(max_length=100)

class Relationship(models.Model):
    model1 = models.ForeignKey(Model1, on_delete=models.CASCADE)
    model2 = models.ForeignKey(Model2, on_delete=models.CASCADE)

这种方式需要手动创建一个关联模型来保存关系,非常繁琐,而且在关系模型中保存的只是两个模型的 ID,不能为关系模型添加任何其他的数据。

Django 中的中间字段就是为了解决这个问题而出现的。

中间字段的概念

中间字段可以被用来在多个模型之间建立多对多关系。我们依然可以使用 ManyToManyField 字段来定义这种关系:

class Model3(models.Model):
    field3 = models.CharField(max_length=100)
    relationships = models.ManyToManyField(
        "Model4",
        through="Relationship2",
        related_name="models3"
    )

class Model4(models.Model):
    field4 = models.CharField(max_length=100)

class Relationship2(models.Model):
    model3 = models.ForeignKey(Model3, on_delete=models.CASCADE)
    model4 = models.ForeignKey(Model4, on_delete=models.CASCADE)
    relationship_data = models.CharField(max_length=100)

这个例子中,我们使用 through 参数来指定中间模型(即 Relationship2),并使用 related_name 参数来指定从 Model4Model3 的反向关联名称。

中间字段的使用

在中间模型中添加字段可以用来保存其它的数据,例如上述代码中的 relationship_data 字段。如下所示,我们可以通过中间字段来查询和设置 Model3Model4 之间的关系:

model3_instance = Model3.objects.create(field3='Model3 instance')
model4_instance = Model4.objects.create(field4='Model4 instance')

relationship2_instance = Relationship2.objects.create(
    model3=model3_instance,
    model4=model4_instance,
    relationship_data='Data for Relationship2'
)

# 添加多个关联对象
model3_instance.relationships.add(model4_instance, through_defaults={'relationship_data': 'Data for Relationship2'})

# 删除多个关联对象
model3_instance.relationships.remove(model4_instance)

# 设置多个关联对象
model3_instance.relationships.set([model4_instance], through_defaults={'relationship_data': 'Data for Relationship2'})

# 获取多个关联对象
model3_instance.model4_set.all()

中间字段能够让我们更加方便地在多个模型之间进行多对多关系的操作,同时也能够存储更多的关联数据。

关联表中存储其他数据

中间字段还可以用来在关联表中存储其他数据,这和数据库中的联合主键和复合主键是类似的。

在这种情况下,我们可以通过编写自定义的中间模型来实现这个功能。

官方文档

Django 中的中间模型,也称作“通过模型(through model)”,可以被用来在多对多关系中存储额外的数据。下面是一个例子:

class Person(models.Model):
    name = models.CharField(max_length=128)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(Person, through='Membership')

class Membership(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)

在这个例子中,Membership 表示一个人加入了一个小组的信息,其中包括了该人加入小组的日期和邀请原因这些信息。

中间模型的使用

在使用自定义中间模型的时候,我们必须使用 through 参数来指定该模型。例如:

class Car(models.Model):
    make = models.CharField(max_length=100)
    model = models.CharField(max_length=100)
    drivers = models.ManyToManyField("Driver", through="Ownership")

class Driver(models.Model):
    name = models.CharField(max_length=100)
    age = models.IntegerField()

class Ownership(models.Model):
    driver = models.ForeignKey(Driver, on_delete=models.CASCADE)
    car = models.ForeignKey(Car, on_delete=models.CASCADE)
    purchase_date = models.DateField()
    notes = models.TextField(null=True)

在这个例子中,我们定义了一个 Car 模型,其中包含了所有车辆的基本信息,以及它们的所有车主。同时,我们还定义了 Driver 模型,以及它们与 Car 之间的关系。

Ownership 模型中,我们存储了每个车辆和每个车主之间的关系,以及购买日期和备注信息。

因为我们定义了一个 through 模型,我们可以把额外的信息存储在中间模型中:

car = Car.objects.create(make='Honda', model='Civic')
driver = Driver.objects.create(name='Alice', age=30)

ownership = Ownership.objects.create(car=car, driver=driver, purchase_date='2022-01-01', notes='Very clean car')

注意: 在访问中间模型时,必须使用关系的名称,而不能使用模型名称。例如:

car = Car.objects.get(id=1)
driver = Driver.objects.get(id=1)

ownership = Ownership.objects.get(car=car, driver=driver)

最后,我们在本文中学习了 Django 中的中间字段的操作。中间字段是一个强大而灵活的工具,它可以被用来处理多个模型之间的多对多关系,以及在关联表中存储其他数据。