【问题标题】:Django modeling, common base and one-to-many relationshipdjango建模,通用基础和一对多关系
【发布时间】:2015-10-09 06:46:41
【问题描述】:

我想创建两个相似的模型 AlbumA 和 AlbumB。

他们都会有歌曲。

class AlbumBase(models.Model):
    class Meta:
        abstract=True

class Song(models.Model):
    album = models.ForeignKey(AlbumBase)  # problem here

class AlbumA(AlbumBase):
    # with specific properties to A (DB fields)
    pass

class AlbumB(AlbumBase):
    # with specific properties to B (DB fields)
    pass

我不认为Song 可以拥有abstract base class 的外键。

我应该如何在 django 中为这些关系建模?

  • 编辑

1。使用多对多字段

根据arie的回答,我可以定义另一边的专辑-歌曲关系,只需注意名称(https://docs.djangoproject.com/en/dev/topics/db/models/#be-careful-with-related-name
另一个区别是,我原来的问题有 1-Many 关系,而这个答案是 Many-Many。(我想要 1-Many,但可以和 M-M 一起生活。)

class AlbumBase(models.Model):

    songs = models.ManyToManyField(Song, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract=True

class Song(models.Model):
    pass

class AlbumA(AlbumBase):
    pass

class AlbumB(AlbumBase):
    pass

2。多表继承

或者我可以使用如下所示的多表继承。

class Album(models.Model):
    pass                        # not abstract

class Song(models.Model):
    album = models.ForeignKey(Album)

class AlbumA(Album):
    pass

class AlbumB(Album):
    pass

3。通用外键(基于 Mark 的回答)

class AlbumBase(models.Model):

    class Meta:
        abstract=True

class Song(models.Model):
    content_type = models.ForeignKey(ContentType, db_index=True, related_name='+')
    object_id = models.PositiveIntegerField(db_index=True)
    album = generic.GenericForeignKey()

class AlbumA(AlbumBase):
    pass

class AlbumB(AlbumBase):
    pass

我应该选择哪一个?
在这些解决方案中,我应该问哪些问题?

【问题讨论】:

  • 具体属性是什么?不同的数据库字段,还是python功能?
  • 如果你够勇敢,你可以试试通用外键。大多数人对它们持负面评价或完全避免它们。但是,不幸的是抽象类不是很OO,只是为了减少代码重复。 docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/…
  • @MarkGalloway:哦,我一直使用通用外键.. 不知道普遍的共识是反对使用它。您是否有任何链接(?在这里想不出更好的术语)来支持您对 GFK 的陈述?
  • 多表继承的问题是你会产生额外的表连接。也许这对您来说不是一个明显的性能影响。很难说。
  • 我刚刚听说要从其他开发人员 IRL 和这里避免使用它们。但是,我确实找到了这篇文章,所以也许我应该吃掉我的帽子。 stackoverflow.com/questions/14333460/…

标签: django model


【解决方案1】:

如果您从抽象类派生模型,最好直接向这些模型添加信息。 您可以尝试将 Song 类链接到 AlbumA 和 AlbumB。

【讨论】:

    【解决方案2】:

    您真的是在谈论具有不同属性和数据库字段的不同类别的专辑吗?

    如果您只关心处理因专辑而异的歌曲,我认为不需要抽象基类,而是像这样对我的模型进行建模:

    class Song(models.Model):
        title = models.CharField(max_length=100)
        ...
    
    class Album(models.Model):
        title = models.CharField(max_length=100)
        songs = models.ManyToManyField(Song)
        ...
    

    或者,如果您确定不存在多张专辑中的歌曲(例如合辑或最佳专辑),您也可以这样做:

    class Song(models.Model):
        title = models.CharField(max_length=100)
        album = models.ForeignKey(Album)
        ...
    
    class Album(models.Model):
        title = models.CharField(max_length=100)
        ...
    

    从您展示和描述的内容看,不需要 GFK 或继承。

    这只是(简单)关系的问题。

    【讨论】:

    • 我也会这样做。如果试图模拟现实世界,将一首歌限制在一张专辑中似乎很奇怪。
    • 啊..这就是区别,其实我是建模博客-评论,我只是觉得歌曲/专辑更容易掌握..
    • 即使你让歌曲指向专辑,仍然不需要抽象基类......除非我错过了什么。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 2011-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多