【问题标题】:OneToMany relationship in Django with one model lockedDjango中的OneToMany关系与一个模型锁定
【发布时间】:2016-03-30 09:57:22
【问题描述】:

我知道 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

这都是伪代码。

如果不使用访问 Django 内部成员的yet another third-party package,这使得项目的前向兼容性更差,我还有哪些选择来实现具有正确架构级约束的正确 OneToManyField?

【问题讨论】:

    标签: django


    【解决方案1】:

    您可以创建另一个中间模型,然后将电话号码 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() 查找用户的电话号码,这将使您的生活更轻松。

    【讨论】:

    • 我认为没有比这更好的了,或者等效的模型继承设置。
    • 啊哈,这在我脑海中起作用了!同意你所说的一切,包括繁琐的部分。
    • 您实际上可以将其定义为从 User 到 PhoneNumber 的 M2M 的直通表,在这种情况下,它变得不那么麻烦了。
    • M2M 实现是否仍然允许一个电话号码属于多个用户的可能性,而 OP 在伪代码中指出这是不可取的? unique_together 约束防止同一个电话号码被多次记录,但不会阻止不同用户共享一个。
    • 是的,我在意识到 M2M(使用 through 或其他方式)是不可能的后问了这个问题。在这个/我的场景中,原始答案仍然比任何其他选项都好。
    猜你喜欢
    • 1970-01-01
    • 2014-01-22
    • 1970-01-01
    • 2016-11-13
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2018-05-21
    • 1970-01-01
    相关资源
    最近更新 更多