【问题标题】:Abstract Models and Foreign Keys in DjangoDjango 中的抽象模型和外键
【发布时间】:2011-11-23 20:50:28
【问题描述】:

我正在从事一个 django 项目,在该项目中我创建了一组三个抽象模型,稍后我将在各种应用程序中使用它们。我遇到的问题是我想通过 ForeignKey 连接这些模型,但 django 告诉我它不能将外键分配给抽象模型。

我当前的解决方案是在我的其他应用程序中实例化类时分配外键。但是,我现在正在为抽象类(书籍和页面)编写一个管理器,并且需要访问这些外键。我基本上想做的是以无状态的方式获取一本书的字数,因此无需将其存储在页面或书籍的字段中。

模型看起来类似于这样:

class Book(models.Models):
    name = models.CharField(...)
    author = models.CharField(...)
    ...

    class Meta:
        abstract = True

class Page(models.Models):
    book = models.ForeignKey(Book)
    chapter = models.CharField(...)
    ...

    class Meta:
        abstract = True

class Word(models.Models):
    page = models.ForeignKey(Page)
    line = models.IntegerField(...)
    ...

    class Meta:
        abstract = True

请注意,这里的这个模型只是为了举例说明我正在尝试做的事情,因此不需要这个模型(Book-Page-Word)从实现的角度来看是否有意义。

【问题讨论】:

    标签: django-models foreign-keys abstract-class


    【解决方案1】:

    也许您在这里需要的是GenericForeignKey,因为您实际上并不知道您的ForeignKeys 将指向什么型号?这意味着您将失去一些正常关系的“类型安全”保证,但它允许您以更一般的方式指定这些关系。见https://docs.djangoproject.com/en/dev/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericForeignKey

    Django 模型继承是一件很酷的事情,并且可以作为使模型 DRYer 的捷径,但并不总是与我们通常对类的多态想法很好地配合。

    【讨论】:

      【解决方案2】:

      这种方法怎么样?我正在考虑自己使用它来延迟关系定义,直到我继承。

      # 这是一个非常做作(但很简单)的例子。

      def AbstractBook(AuthorModel):                                                  
          class AbstractBookClass(Model):                                             
              name = CharField(max_length=10)                                         
              author = ForeignKey(AuthorModel)                                        
              class Meta:                                                             
                  abstract = True                                                     
          return AbstractBookClass                                                    
      
      
      class AbstractAuthor(Model):                                                    
          name = CharField(max_length=10)                                             
          class Meta:                                                                 
              abstract = True                                                         
      
      
      class BadAuthor(AbstractAuthor):                                                
          pass                                                                        
      
      class BadBook(AbstractBook(BadAuthor)):                                         
          pass                                                                        
      
      class GoodAuthor(AbstractAuthor):                                               
          pass                                                                        
      
      class GoodBook(AbstractBook(GoodAuthor)):                                       
          pass                                                                        
      

      【讨论】:

      • 读到这让我很受伤
      【解决方案3】:

      两件事:

      1) 如前所述,按照您构建架构的方式,您将需要一个 GenericForeignKey。但是您必须考虑到 Book through Page 与 Word 具有 多对多 关系,而 GenericForeignKey 只是实现 一对多。对于规范化模式,Django 没有任何开箱即用的东西。您将要做的(如果您关心规范化)是自己实现中间体(对于具体模型使用“通过”)。

      2) 如果您关心语言处理,考虑到生成的数据库大小和几十本书后的查询时间,使用关系数据库(有或没有 Django 的 ORM)不是一种非常有效的方法。此外,由于抽象模型,您需要查找连接的额外列,它很快就会变得非常不切实际。我认为根据您的查询和视图研究其他方法会更有益,例如仅存储聚合和/或非规范化(在这种情况下甚至研究非关系存储系统)。

      【讨论】:

        猜你喜欢
        • 2016-04-19
        • 2016-06-24
        • 1970-01-01
        • 2018-07-09
        • 1970-01-01
        • 2020-11-13
        • 1970-01-01
        • 2015-03-07
        • 2019-02-06
        相关资源
        最近更新 更多