Django circular depenceny ForeignKey vs ManyToManyField

时间:2016-05-10 11:28:08

标签: python django

对于一个项目,我有几个Django应用程序。 目标是公司或联系人可以包含无限数量的联系信息。 (电话,电子邮件,地址)

我认为创建一个core应用程序是一个不错的选择,我会在其中放置电话,地址,语言,国家等模型...... 我想将它们放在core应用程序中,因为它们将在整个项目中用于多个应用程序。

其次,我有一个contact_management应用程序,其中公司和联系人是模型。

所以这就是它的样子

core / models.py

from contact_management.models import Contact, Company    

class Language(models.Model):
    name = models.CharField(max_length=100)

class Phone(models.Model):
    number = models.CharField(max_length=25)

    company = models.ForeignKey(Company, related_name='phone_numbers')
    contact = models.ForeignKey(Contact, related_name='phone_numbers')

contact_management / models.py

from core.models import Language

class Company(models.Model):
    name = models.CharField(max_length=255)

class Contact(models.Model):
    name = models.Charfield(max_length=255)
    language = models.ForeignKey(Language)

最终出现了循环依赖和错误Cannot import Language

所以在那之后我开始使用many2many字段,所以我可以扭转依赖。

core / models.py

class Language(models.Model):
    name = models.CharField(max_length=100)

class Phone(models.Model):
    number = models.CharField(max_length=25)

contact_management / models.py

from core.models import Language

class Company(models.Model):
    name = models.CharField(max_length=255)
    phone_numbers = models.ManyToManyField(Phone, blank=True, null=True)

class Contact(models.Model):
    name = models.Charfield(max_length=255)
    language = models.ForeignKey(Language)
    phone_numbers = models.ManyToManyField(Phone, blank=True, null=True)

这可能会有效,但管理员不允许我在管理员中使用TabularInline来显示详细信息,或让我更新联系人或公司表单中的字段。

另外,我不太喜欢ManyToManyField,因为每个联系信息实例(电话,电子邮件)只有一个联系人或公司。

contact_management / admin

class CompanyPhoneInline(admin.TabularInline):
    model = Company.phone_numbers.through

@admin.site.register(Phone)
class CompanyAdmin(admin.ModelAdmin):
    fields = ["company_name", "bank_account_number", "tax_id",
              "chamber_of_commerce_id", "active"]
    inlines = [CompanyPhoneInline, ]

也许这只是我在这里缺少的细节,或者我应该遵循另一种设计模式。我希望有人可以帮我解决这个问题。

1 个答案:

答案 0 :(得分:5)

由于INSTALLED_APPS中的应用顺序或帖子中的特定情况,您可能会遇到这些问题。

Django建议在这种情况下(link):

  

如果需要在尚未定义的模型上创建关系,可以使用模型的名称,而不是模型对象本身。

     

...

     

要引用另一个应用程序中定义的模型,您可以使用完整的应用程序标签明确指定模型。

     

这种引用在解析两个应用程序之间的循环导入依赖关系时非常有用。

因此,您可以使用Language

而不是'core.Language'
class Contact(models.Model):
    name = models.Charfield(max_length=255)
    language = models.ForeignKey('core.Language')

此处,coreapp_labelLanguage是模型类名称。

我建议您使用此完整的应用程序标签(字符串版本)来定义您的相关字段,例如ForeignKeyManyToMany等。所以你永远不会遇到这些问题。