ContentTypes 的应用

Posted zhang-zi-yi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ContentTypes 的应用相关的知识,希望对你有一定的参考价值。

ContentTypes

  • django 中的一个应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口。

  • Contenttypes应用的核心是ContentType模型

    位于: django.contrib.contenttypes.models.ContentType

  • django 创建项目之后会 会自动在配置文件中安装好 中间件中的‘django.contrib.contenttypes‘,

  • 执行数据库迁移命令之后 数据中会创建一个名为django_content_type的表

    • 记录了 :
    • app_label字段存储了APP的名称,model字段存储了APP下的具体的模型类的名称。

主要用来做表跟表之间的关联:

应用场景:

表结构 : 发表的说说表 发表的图片 以及 每张表的评论内容

使用 : ContentType 表 在评论表中 定义外键 关联 这张表

? 因为: 一条数据 或一张图片 会有 多条评论 多对一 的关系 还要加一个 对应的 对象id 的字段 作为关联

但是 : 关联的 ContentType 表 和 每张表的 对象的 id 没有关系 所以 就用到了 GenericForeignKey 将这两个字段关联起来 content_object = GenericForeignKey(‘table_name‘, ‘obj_id‘) 注意:这两个参数顺序不能乱 这个字段 不会在数据库中创建

通过 说说 或者 图片 来 查询关联的 评论 因为没有 实际的 关联 这就用到了 GenericRelation 用于 反向查询

comments = GenericRelation(‘Comment‘, object_id_field=‘obj_id‘, content_type_field=‘table_name‘)

注意 object_id_fieldcontent_type_field 参数 如果 评论表中 定义的 contenttype外键 和 关联的 外键的 id 字段 的 两个字段名 为 object_idcontent_type 就不用 修改这两个参数 使用默认的就行 如果 名字是自定义的 就要 更改 这两个参数 指定 对应的 字段名

model表结构:

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
# Create your models here.

class Talk(models.Model):
    """说说"""
    info = models.TextField()
    comments = GenericRelation(‘Comment‘, object_id_field=‘obj_id‘, content_type_field=‘table_name‘)


class Picture(models.Model):
    """图片"""
    img = models.CharField(max_length=128)
    # 方便反向查询的时候 (不会再数据库中创建这个字段,只是提供了一些方便操作的方法)
    comments = GenericRelation(‘Comment‘, object_id_field=‘obj_id‘, content_type_field=‘table_name‘)


class Comment(models.Model):
    """评论"""
    info = models.TextField()
    # talk = models.ForeignKey(to=‘Talk‘, null=True, on_delete=models.CASCADE)
    # picture = models.ForeignKey(to=‘Picture‘, null=True, on_delete=models.CASCADE)

    # 关联表的表名(外键 --> Django Content Type表)
    table_name = models.ForeignKey(to=ContentType)
    # 关联表中具体的数据id
    obj_id = models.IntegerField()
    # 告诉Django table_name和obj_id是一组动态关联的数据
    content_object = GenericForeignKey(‘table_name‘, ‘obj_id‘)

查询时:

# 创建数据
talk_obj = models.Talk.objects.create(info=‘随便说点什么‘)

# 创建评论对象 可以将 被关联的 talk_obj  直接 传递给 这张表的 content_object 字段 可以直接保存数据 
models.Comment.object.create(info=‘写的什么鬼东西!‘, content_object=talk_obj)


# 通常反向查询  根据 实际发表的  内容 查询该内容的 评论

# 通过 单一的图片 查询 该对象对应的所有评论
ret = models.Picture.objects.filter(id=1).farst()
# 直接使用 管理对象 中添加的 用于反向查询的字段 来查询这个字段对应的 所有的数据
comment_all = ret.comments.all()
print(comment_all)

# 正向查询  注意:  table_name_id  对应的是 关联的 contenttype表中保存的 对应的models 表的名字 的 id  # 也就是对应的表   obj_id  对应的 是这张表中对应的单个对象的  id 
ret = models.Comment.objects.filter(table_name_id=4, obj_id=3)
print(ret)  

以上是关于ContentTypes 的应用的主要内容,如果未能解决你的问题,请参考以下文章

Django contenttypes 应用

20,Django contenttypes 应用

8.12 Django contenttypes组件

django -- contenttypes组件

如何使用 Django 管理员的 ContentTypes 在两个应用程序之间访问 ManyToManyField?

Django应用之content type(app应用之一django.contrib.contenttypes)