Django中的抽象模型和外键

时间:2011-09-23 17:31:14

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

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

我目前的解决方案是在我在其他应用程序中实现该类时指定外键。但是,我正在为抽象类(书和页)编写一个管理器,并且需要访问这些外键。我基本上要做的是以无状态的方式获得一本书所拥有的单词数量,因此不会将其存储在页面或书籍的字段中。

模型看起来与此相似:

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)是否合理。

3 个答案:

答案 0 :(得分:13)

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

Django模型继承是一件很酷的事情,很好地作为使你的模型DRYer的快捷方式,但并不总能很好地适应我们通常的类的多态性想法。

答案 1 :(得分:4)

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

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

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                                                                        

答案 2 :(得分:0)

两件事:

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

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