在Django中使用一个被锁定的模型的一对多关系。
在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?
在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()`来查询用户的电话号码。
以上两种解决方法是最好的选择,无论是使用中间模型还是等效的模型继承设置。