Django中的OneToMany关系锁定了一个模型

时间:2015-12-23 22:18:26

标签: django

我知道ForeignKeys和OneToOneFields是什么,以及ManyToManyField,它们如何工作以及何时使用它们。但是,我正在使用一个项目,该项目的 Many 部分无法修改。所以,假设I want to let a user have many phone numbers,我通常会这样做:

# my_app/models.py
from django.db import models
class User(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):
    # This cannot change

# my_app/models.py
from django.db import models
from third_party_django_package.models import PhoneNumber
class User(Model):
    # These do not work -- a user can have more than one phone number
    phone_number = models.ForeignKey(PhoneNumber)
    phone_number = models.OneToOneField(PhoneNumber)

    # This is close, but I want a phone number to belong to only one User
    phone_numbers = models.ManyToManyField(PhoneNumber, related_name=...)

    def clean(self):
        # Validating the M2M relation costs extra queries, is slow, and 
        # is prone to race conditions

这都是伪代码。

不使用yet another third-party package来访问Django的内部成员,这使得项目更加向前兼容,我还有什么选择来实现具有正确模式级约束的正确OneToManyField?< / p>

1 个答案:

答案 0 :(得分:8)

您可以创建另一个中间模型,然后将电话号码OneToOneField设置为该模型,然后在该模型中将User定义为ForeignKey。

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

这有点麻烦,但至少可以实现你所需要的。

修改

正如@Daniel所说,可以使用与through模型的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()查看用户的电话号码,这将使您的生活更轻松。