zoukankan      html  css  js  c++  java
  • Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构

    在建立数据库时,通常会把各个对象的属性放在一个一个表中,通过表之间的关系即外键来描述和约束业务逻辑。

    Django 的 ORM 模型简化了一些数据库的操作,特别是外键,以及查询等功能,使得我们不用再写复杂的sql语句。

    表和关系的逻辑清晰并且可以跨数据库平台使用。

    下面主要记录一下 Django 在数据库中是怎样处理 ForeignKey 的。

    app 都是 Pinax 中所集成的。

    1、ManyToManyField

     

    class Url(models.Model):
    .........
        class Meta:
            verbose_name = _('url')
            verbose_name_plural = _('url')
    
    class Rule(models.Model):
    .........
    
        allowed = models.ManyToManyField(Url, blank=True, related_name="allowed",
                                         help_text=_("The URLs which are allowed "
                                                     "to be accessed by bots."))
    
        disallowed = models.ManyToManyField(Url, blank=True, related_name="disallowed",
                                            help_text=_("The URLs which are not "
                                                        "allowed to be accessed "
                                                        "by bots."))
        sites = models.ManyToManyField(Site)
    

    如上是 robots.models

    在数据库中表现为

    图[1]

    robots_rule 和 robots_url 两个表对应两个 model

    robots_rule_allowed, robots_rule_disallowed, robots_rule_sites 三个表分别对应 ManyToManyField

    如果在 rule 中查询 rule.allowed,Django 会自动锁定外键对应的表为 robots_rule_allowed 通过查询这个表得到对应的 url_id(多个),然后去 robots_url 表中提取相应记录。

    2、ForeignKey

    class ThreadedComment(models.Model):
    .......
        # Generic Foreign Key Fields
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField(_('object ID'))
        content_object = generic.GenericForeignKey()
        
        # Hierarchy Field
        parent = models.ForeignKey('self', null=True, blank=True, default=None, related_name='children')
            
        # User Field
        user = models.ForeignKey(User)
    

    先看 ForeignKey 字段。

    在表 threadedcomments_threadedcomment 中的结构如下(注意这个表名是由 <app_label>_<models_model> 组成)

    图[2]

    parent 是指向自身表的约束(用来表示一组回复,可以呈现 tree 形式的回复),允许为空,字段值为父 item 的 pk 值(即 id )。

    查询时,Django 会提取 parent_id 值,然后直接在自身表中搜索到父 id,即被回复的评论。

    注,所有的 model 不用给出 id 字段描述,因为 Django 会自动给出,而且做外键关联都是由 id 字段唯一确定的,当然这可以改...看document。

    user 是指向另一个表(Django 默认app User,用于登陆后台 admin)的外键,提取 user_id 值,再去 User 表中查询即可。


    ForeignKey 的 related_name='children' 标注了反向关系名称。

    例如,这个例子中指向的是 parent,而 parent 中没有任何标注,但是我们可以通过 <parent对象>.<children>+<_set> 

    parent对象.children_set() 来得到所有的 children 关联记录。


    3、GenericForeignKey

    这个东西比较好用,在我没有知道这个好东西之前,解决一个表关联多个外键时,是通过定义一个 type 字段来确定当前记录中的哪个外键是有效的。

    当然他这个原理也是这样的,不过多加了一个全局的 ContentType 表,使整体结构更加清晰。

    例如,我们还是拿上面的评论来做例子。为了使数据表结构清晰,评论都放在一个表中,那么,一个评论就可能是 blog 的, tweets 的,也可能是 shop 的。

    那就要定义一个 ContentType GenericForeignKey 来动态存储和得到外键所关联的表信息。

    content_type 是关联到 ContentType model 上的一个外键,实际上是一个 integer ,表示所关联的表类别,例如 blog post 表。

    object_id 标识的是所关联表中记录的 id 值,例如 post 表中的一个 blog 记录。

    content_type, object_id 是默认的值,如果需要更改可以在创建 GenericForeignKey 时传参。

    下面看看 django_content_type 表的结构

    图[3]

    app_label, model 组合是 UNIQUE

    app_label 是 app 的名称。

    model 是 app models 中的 model 名称。

    图[2]中content_type_id 和 object_id 分别对应的就是 model 中声明的 content_type 和 object_id 字段。

    通过content_type_id 可以在图[3]django_content_type 表中查询到对应关联的 

    名称name(verbose_name) 名称app_label(app名称) model名称(model的小写)


    通过 app_label, model 两个字段的拼接就可以得到表名,例如 id=41 blog_post 即为 content_type_id=41 对应的数据表,

    说明 comment(id=1-7) 对应的是 blog app 的 post 数据表。


    OK就是这样,其实很简单的东西,框架非常清晰,看文档的时候晕晕的。

  • 相关阅读:
    Read-Copy Update Implementation For Non-Cache-Coherent Systems
    10 华电内部文档搜索系统 search04
    10 华电内部文档搜索系统 search05
    lucene4
    10 华电内部文档搜索系统 search01
    01 lucene基础 北风网项目培训 Lucene实践课程 索引
    01 lucene基础 北风网项目培训 Lucene实践课程 系统架构
    01 lucene基础 北风网项目培训 Lucene实践课程 Lucene概述
    第五章 大数据平台与技术 第13讲 NoSQL数据库
    第五章 大数据平台与技术 第12讲 大数据处理平台Spark
  • 原文地址:https://www.cnblogs.com/sunblackshine/p/1947795.html
Copyright © 2011-2022 走看看