2015-12-23 33 views
1

我知道ForeignKeys和OneToOneFields是什麼,以及ManyToManyField,它們是如何工作的以及何時使用它們。但是,我正在與一個項目合作,其中部分關係不能修改。因此,假設I want to let a user have many phone numbers,我通常會做到這一點:Django中的OneToMany關係,鎖定了一個模型

# 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?

回答

7

您可以創建另一箇中間模型,然後將電話號碼OneToOneField作爲該模型,然後在該模型中將User定義爲ForeignKey。

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

這有點麻煩,但至少它達到了你所需要的。

編輯:

正如@Daniel說,它可能在領域做到這一點使用M2M關係與through型號,同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

我不認爲你可以做得比這更好,或者等效的模型繼承設置。 –

+0

啊哈,這在我的腦海裏工作!同意你所說的一切,包括繁瑣的部分。 – Brian

+0

您可能實際上可以將其定義爲從用戶到PhoneNumber的M2M的通過表,在這種情況下,它變得非常麻煩。 –