在Django中使用一个被锁定的模型的一对多关系。

18 浏览
0 Comments

在Django中使用一个被锁定的模型的一对多关系。

我了解ForeignKeys和OneToOneFields,以及ManyToManyField,知道它们是如何工作的以及何时使用它们。然而,我正在处理一个项目,其中关系的"Many"部分无法修改。所以,假设我想让一个用户有多个电话号码,我通常会这样做:

# my_app/models.py
from django.db import models
class User(models.Model):
    ...
class PhoneNumber(models.Model):
    user = models.ForeignKey(User)

我遇到的问题是,我的PhoneNumber模型等效是来自一个第三方包的,已经填充了记录,并且没有在我的应用中进行子类化。即:

# third_party_django_package/models.py
from django.db import models
class PhoneNumber(models.Model):
    # 这部分无法更改
# my_app/models.py
from django.db import models
from third_party_django_package.models import PhoneNumber
class User(models.Model):
    # 这些都不起作用 - 一个用户可以有多个电话号码
    phone_number = models.ForeignKey(PhoneNumber)
    phone_number = models.OneToOneField(PhoneNumber)
    # 这个接近,但我希望一个电话号码只属于一个用户
    phone_numbers = models.ManyToManyField(PhoneNumber, related_name=...)
    def clean(self):
        # 验证M2M关系需要额外的查询,速度慢,并且容易产生竞争条件

这只是伪代码。

在不使用访问Django内部成员的第三方包的情况下,这使得项目变得更不兼容,我还有哪些选择来实现正确的带有正确模式级约束的OneToManyField?

0
0 Comments

在Django中使用一对多关系的一个模型被锁定时,会出现以下问题:无法直接在一个模型中将一个字段设置为该模型的外键。解决这个问题的方法是创建另一个中间模型,并将电话号码设置为该模型的一对一字段,然后在该模型中将用户设置为外键。可以使用以下代码实现:

class UserPhoneNumber(models.Model):
    phone_number = models.OneToOneField(PhoneNumber)
    user = models.ForeignKey(User)

这样做有点繁琐,但至少可以实现所需的功能。

另一种解决方法是使用M2M关系,并在通过模型中使用unique_together字段来限制字段的唯一性。可以使用以下代码实现:

class User(Model):
    phone_numbers = models.ManyToManyField(PhoneNumber, through=UserPhoneNumber)
class UserPhoneNumber(Model):
    phone_number = models.ForeignKey(PhoneNumber)
    user = models.ForeignKey(User)
    class Meta:
        unique_together = ('phone_number', 'user')

这样做可以更方便地通过`numbers = user.phone_numbers.all()`来查询用户的电话号码。

以上两种解决方法是最好的选择,无论是使用中间模型还是等效的模型继承设置。

0