介绍

Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口。
Contenttypes应用的核心是ContentType模型,位于django.contrib.contenttypes.models.ContentType。 ContentType的实例表示并保存项目中安装的模型的信息,每当有新的模型时会自动创建新的ContentType实例。
只要使用django-admin startproject 命令创建的Django项目(PyCharm创建Django项目同理),默认都会在settings.py的INSTALLED_APPS列表中安装好django.contrib.contenttypes。
我们执行了数据迁移命令之后,会自动在数据库中创建一个名为django_content_type的表。
表结构如下图所示:
其中,app_label字段存储了APP的名称,model字段存储了APP下的具体的模型类的名称。

应用场景

我们在网上po一段散文诗也可以po一张旅途的风景图,文字可以被评论,图片也可以被评论。我们需要在数据库中建表存储这些数据,我们可能会设计出下面这样的表结构。

class Post(models.Model):
"""帖子表"""
author = models.ForeignKey(User)
title = models.CharField(max_length=72) class Picture(models.Model):
"""图片表"""
author = models.ForeignKey(User)
image = models.ImageField() class Comment(models.Model):
"""评论表"""
author = models.ForeignKey(User)
content = models.TextField()
post = models.ForeignKey(Post, null=True, blank=True, on_delete=models.CASCADE)
picture = models.ForeignKey(Picture, null=True, blank=True, on_delete=models.CASCADE)

这表结构看起来不太简洁,我们画个图来看一下:

能用是能用,但是评论表有点冗余啊。好多列都空着呢啊!

我们优化一下,我们在评论表里不直接外键关联 文字和图片,而是存储一下关联的表名和字段,这样就好很多了。

看下图:

那我们不妨步子再大一点,再往前走一步试试,因为表名在评论里面重复了很多次,我们完全可以把Django项目中的表名都存储在一个表里面。然后评论表里外键关联这个表就可以了。

这个时候我们就用上了前面讲到的contenttypes,借助contenttypes我们就能够在创建Comment的时候再决定和Post关联还是和Picture关联。
在models.py中使用django.contrib.contenttypes中提供的特殊字段GenericForeignKey来实现:
class Comment(models.Model):
"""评论表"""
author = models.ForeignKey(User)
content = models.TextField() content_type = models.ForeignKey(ContentType) # 外键关联django_content_type表
object_id = models.PositiveIntegerField() # 关联数据的主键
content_object = GenericForeignKey('content_type', 'object_id')

contenttypes使用

import os

if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_contenttype.settings") import django
django.setup() from app01.models import Post, Picture, Comment
from django.contrib.auth.models import User
# 准备测试数据
user_1 = User.objects.create_user(username='aaa', password='123')
user_2 = User.objects.create_user(username='bbb', password='123')
user_3 = User.objects.create_user(username='ccc', password='123') post_1 = Post.objects.create(author=user_1, title='Python入门教程')
post_2 = Post.objects.create(author=user_2, title='Python进阶教程')
post_3 = Post.objects.create(author=user_1, title='Python入土教程') picture_1 = Picture.objects.create(author=user_1, image='小姐姐01.jpg')
picture_2 = Picture.objects.create(author=user_1, image='小姐姐02.jpg')
picture_3 = Picture.objects.create(author=user_3, image='小哥哥01.jpg') # 给帖子创建评论数据
comment_1 = Comment.objects.create(author=user_1, content='好文!', content_object=post_1)
# 给图片创建评论数据
comment_2 = Comment.objects.create(author=user_2, content='好美!', content_object=picture_1)
接下来如果我们想要查看某篇帖子或者某个照片的所有评论,这个时候就可以用上另外一个工具--GenericRelation了。
from django.contrib.contenttypes.fields import GenericRelation
修改models.py中的Post和Picture,添加用于反向查询的comments字段:
class Post(models.Model):
"""帖子表"""
author = models.ForeignKey(User)
title = models.CharField(max_length=72) comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段) class Picture(models.Model):
"""图片表"""
author = models.ForeignKey(User)
image = models.ImageField() comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段)

查询示例:

post_1 = Post.objects.filter(id=1).first()
comment_list = post_1.comments.all()

Python contenttypes组件的更多相关文章

  1. Django contenttypes 组件

    contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...

  2. Django contenttypes组件

    contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...

  3. contenttypes组件 (处理大量外键)

    介绍 Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation).   https://www.cnblogs.com/huchong ...

  4. Django之contenttypes组件

    目录 一. 介绍 二. 应用场景 1. 表结构设计的演变 2. GenericForeignKey和GenericRelation 3. 测试 一. 介绍 Django包含一个contenttypes ...

  5. Python标准组件ConfigParser配置文件解析器,保存配置时支持大写字母的方法

    虽然自己已经改用xml作为配置文件首选格式了,但是有时候还是需要解析ini.cfg文件(为了兼容早期版本或者其他作者的软件). 基本上Python自带的ConfigParser足够应对了,但是美中不足 ...

  6. Python常用组件、命令大总结(持续更新)

    Python开发常用组件.命令(干货) 持续更新中-关注公众号"轻松学编程"了解更多. 1.生成6位数字随机验证码 import random import string def ...

  7. Python分页组件

    分页组件的实现: class Pagination(object): """ 自定义分页 """ def __init__(self,cur ...

  8. Python - Django - 组件

    网站中通常会有一个导航条,如下图 这个导航条在很多页面都会存在 可以把导航条做成一个组件,让要显示导航条的网页包含 导航条组件 nav.html: <h1>假装这是一个导航条</h1 ...

  9. python 日志组件

    日志组件: import logging import logging.handlers import os class logs(object): def __init__(self): self. ...

随机推荐

  1. python如何用pip安装模块

    pip去python官网下载 我想写的是安装后怎么做,假设我们要安装pymysql模块 在python交互式模式中运行pip install pymysql 会抛出 语法错误,不知为何. 此时应该找到 ...

  2. layui 单选框选中事件

    <div class="layui-form-item" pane=""> <label class="layui-form-lab ...

  3. Bear and Tower of Cubes Codeforces - 680D

    https://codeforces.com/contest/680/problem/D 一道2D,又是搞两个小时才搞出来...不过好在搞出来了 官方题解:可以证明对于m,设a是满足a^3<=m ...

  4. python入门之json与pickle数据序列化

    前提实例: 将一个字典存放在文件里 #存入数据info = { 'name':'chy', 'age':18 } f = open("test.txt","w" ...

  5. c/c++学习系列之内存对齐

    1.C++内存对齐规则 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数).程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你 ...

  6. hdu 5971 Wrestling Match 判断能否构成二分图

    http://acm.hdu.edu.cn/showproblem.php?pid=5971 Wrestling Match Time Limit: 2000/1000 MS (Java/Others ...

  7. mouseover等闪烁问题

    在使用mouseover等鼠标事件时如移动上去灰色的遮罩层高度从0到100% 在操作中发现鼠标一直在图里面但遮罩会一直变化,我感觉应该是遮罩层出现后导致鼠标离开了底层图片所以会一直变化.想起之前用的 ...

  8. mysql写存储过程并定时调用

    设置一个定时任务:运行以下SQL -- 创建一个表test:字段endtime CREATE TABLE test (endtime DATETIME);   -- 创建函数 :向test插入endt ...

  9. Emacs Org-mode中英文字体设置

    Emacs Org-mode中英文字体设置 Table of Contents 1. 缺省字体存在的问题 2. 解决方法 2.1. 环境说明 2.2. 思路和方法 2.3. emacs设置代码 2.4 ...

  10. ios自定义日期、时间、城市选择器

    选择器,我想大家都不陌生,当需要用户去选择某些范围值内的一个固定值时,我们会采用选择器的方式.选择器可以直观的提示用户选择的值范围.统一信息的填写格式,同时也方便用户快速的进行选择,比如对于性别,正常 ...