繁体   English   中英

Django - 根据其内容引用两个表之一的外键

[英]Django - Foreign key referencing one of two tables depending on its content

我在我的数据库模型设计中遇到了死胡同,可以使用一些帮助。 我们使用 Postgres 数据库和 django 框架来存储各种论文、书籍等。

这些是我遇到问题的基类:

class Publisher(models.Model):
    name = models.CharField(unique=True)
    website = models.URLField(blank=True)
    #...

class Editor(models.Model):
    firstname = models.CharField()
    lastname = models.CharField()
    #...

class Book(models.Model):
    title = models.CharField(unique=True)
    #...
    editors = models.ManyToManyField(Editor, blank=True)
    publisher = models.ForeignKey(Publisher, blank=True)
    #...

上面的 Editor 类被建模为将编辑器存储为相应书籍的人,例如。 “瑞恩·凯里”或“尼古拉斯·罗”。 Publisher 类将包含诸如“芝加哥大学出版社”之类的信息。

问题舱口应该编辑器和出版商是相同的。 例如,编辑和出版商都应该是“芝加哥大学出版社”。

现在,每当通过 django-admin 界面将新书保存到数据库时,我希望发生以下情况:

  • 如果给出了一个或多个编辑器,则将其保存为上面的模型。
  • 如果没有给出编辑者但给出了发布者,则使编辑者指向与发布者指向的相同的关键
  • 如果两者都没有给出,则将两者都留空

我正在考虑以某种方式实现它:

class Book:
#...
    def save(self, *args, **kwargs):
        if self.editors.count() <= 0 and self.publisher:
            self.editors = self.publisher #This is not possible
        super(Book, self).save(*args, **kwargs)

self.editors = self.publisher 位也许可以通过继承来修复,但仍然有多个编辑器和只有一个发布者,我不希望发布者和编辑器存储在同一个表中。

关于如何解决这个问题的任何想法?

几乎不需要重新构建您的模型,这是可能的,并且比现在更加灵活。

第一:不要将发布者和编辑者置于 2 个不同的模型中。 做一个。

第二:如果您可以同时拥有个人和组织/公司的出版商/编辑器(这将需要不同的模型字段),请将所有常见字段放入一个模型中,并制作 2 个将从该模型继承的模型,其中包含更多指定的字段。 这将在引擎盖下创建字段之间的一对一关系。

第三:在您的图书模型中创建 2 个字段,一个ForeignKey命名为publisher和一个ManyToMany命名为editors 这两个关系都应该指向您的发布者/编辑者的基本模型。

示例代码:

class PEBase(models.Model): # have no idea how to name it better

    some_common_field = models.Field(...)


class PEPerson(PEBase):

    first_name = models.CharField()
    last_name = models.CharField()


class PEOrganization(PEBase):

    name = models.CharField()
    website = models.URLField()


class Book(models.Model):

    title = models.CharField(unique=True)
    #...
    editors = models.ManyToManyField(PEBase, blank=True, related_name="books_edited")
    publisher = models.ForeignKey(PEBase, blank=True, related_name="books_published")

    def save(self, *args, **kwargs):
        super(Book, self).save(*args, **kwargs)
        if self.editors.count() <= 0 and self.publisher:
            self.editors.add(self.publisher) #This must go after save - ID of book must be already set.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM