Django之contenttypes组件
一. 介绍
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下的具体的模型类的名称.
二. 应用场景
1. 表结构设计的演变
举个简单的例子, 我们可以在某个平台单独发文章, 也可以单独发图片, 每一篇文章或每一张图片都可以被不同的用户评论. 如此一来, 我们就可以设计出以下表结构:
app01/models.py
文件:
from django.db import models
class UserInfo(models.Model):
"""用户表"""
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
class Post(models.Model):
"""帖子表"""
author = models.ForeignKey(to='UserInfo')
title = models.TextField()
class Picture(models.Model):
"""图片表"""
author = models.ForeignKey(to='UserInfo')
image = models.CharField(max_length=128)
class Comment(models.Model):
"""评论表"""
author = models.ForeignKey(to='UserInfo')
content = models.TextField()
post = models.ForeignKey(to='Post', null=True, blank=True, on_delete=models.CASCADE)
picture = models.ForeignKey(to='Picture', null=True, blank=True, on_delete=models.CASCADE)
图示说明:
从上表可以看出, Comment
表的post
字段和picture
字段下的数据有较多的空余, 造成了数据库空间的浪费. 于是, 我们尝试进行这样的改进:
其中, table_name
指该条评论对应的表名(帖子?图片?), object_id
指该表名对应的表中某条记录的id.
如此一来, 进一步思考, 我们不妨再设计一个表django_content_type
, 里面专门存放表名, 用Comment
表关联django_content_type
表, 把原先的table_name
换成表名对应的id.
2. GenericForeignKey
和GenericRelation
这个时候我们就用上了前面讲到的contenttypes
, 借助contenttypes
我们就能够在创建Comment
的时候再决定和Post关联还是和Picture关联.
在app01/models.py
中:
- 使用
django.contrib.contenttypes
中提供的特殊字段GenericForeignKey
来实现表与表之间的关联(不会再数据库中创建新的字段). - 使用
GenericRelation
进行反向查询.
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class UserInfo(models.Model):
"""用户表"""
id = models.AutoField(primary_key=True)
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
class Post(models.Model):
"""帖子表"""
author = models.ForeignKey(to='UserInfo')
title = models.TextField()
comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段)
class Picture(models.Model):
"""图片表"""
author = models.ForeignKey(to='UserInfo')
image = models.CharField(max_length=128)
comments = GenericRelation('Comment') # 支持反向查找评论数据(不会在数据库中创建字段)
class Comment(models.Model):
"""评论表"""
author = models.ForeignKey(to='UserInfo')
content = models.TextField()
# content_type是关联的表名
content_type = models.ForeignKey(to=ContentType) # 外键关联django的ContentType表
# object_id是关联表中具体的数据id
object_id = models.PositiveIntegerField() # 关联数据的主键
# 通过GenericForeignKey把以上二者(表名, 该表中具体数据id)动态关联起来
content_object = GenericForeignKey('content_type', 'object_id')
3. 测试
在Django项目根目录下创建一个用于测试的文件text.py
:
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_contenttype.settings")
import django
django.setup()
#### 以上代码是Django环境的准备 ####
from app01 import models
# 准备测试数据
user_1 = models.UserInfo.objects.create(username='aaa', password='123')
user_2 = models.UserInfo.objects.create(username='bbb', password='123')
user_3 = models.UserInfo.objects.create(username='ccc', password='123')
post_1 = models.Post.objects.create(author=user_1, title='Python入门教程')
post_2 = models.Post.objects.create(author=user_2, title='Python进阶教程')
post_3 = models.Post.objects.create(author=user_1, title='Python入土教程')
picture_1 = models.Picture.objects.create(author=user_1, image='小姐姐01.jpg')
picture_2 = models.Picture.objects.create(author=user_1, image='小姐姐02.jpg')
picture_3 = models.Picture.objects.create(author=user_3, image='小哥哥01.jpg')
# 给帖子创建评论数据
comment_1 = models.Comment.objects.create(author=user_1, content='好文!', content_object=post_1)
# 给图片创建评论数据
comment_2 = models.Comment.objects.create(author=user_2, content='好美!', content_object=picture_1)
# 查询示例
post_1 = models.Post.objects.first()
ret = post_1.comments.values()
print(ret)
Django之contenttypes组件的更多相关文章
- Django contenttypes 组件
contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...
- Django contenttypes组件
contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Conte ...
- django内置组件——ContentTypes
一.什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象 ...
- 【django之stark组件】
一.需求 仿照django的admin,开发自己的stark组件.实现类似数据库客户端的功能,对数据进行增删改查. 二.实现 1.在settings配置中分别注册这三个app # Applicatio ...
- django 之 stark组件
----------------------------------------------------------------烦恼没完没了,内心动荡不安,呜呼哀哉. 一.有个特殊的需求,需要用sta ...
- Django之ContentType组件
一.理想表结构设计 1.初始构建 1. 场景刚过去的双12,很多电商平台都会对他们的商品进行打折促销活动的,那么我们如果要实现这样的一个场景,改如何设计我们的表? 2. 初始表设计 注释很重要,看看吧 ...
- python框架之Django(13)-admin组件
使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLED_APPS ...
- Django组件(五) Django之ContentType组件
基础使用 -contenttype组件 -django提供的一个快速连表操作的组件,可以追踪项目中所有的APP和model的对应关系,并记录在ContentType表中. 当我们的项目做数据迁移后,会 ...
- Django 之 admin组件使用&源码解析
admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.可以在项目的 settings.py 中的 INSTALLED ...
随机推荐
- C++获取文件夹下所有文件的路径
代码 getFiles()函数的作用: path是一个文件夹路径,函数在path文件夹下寻找所有文件(包括子文件夹下的文件),然后将所有文件的路径存入files #include <io.h&g ...
- bat 获取当前文件夹的文件名
bat 获取当前文件夹的文件名 @echo off pushd %1 & for %%i in (.) do set curr=%%~ni echo %curr% pause
- BFS和DFS
1.图的两种遍历方式 图的遍历通常有两种方式,即深度优先搜索(Depth First Search)和广度优先搜索(Breadth First Search).前者类似于树的先序遍历,而后者类似于树的 ...
- WPF DevExpress ChartControl使用之PieChart
饼状图要比XYDiagram要简单一点,大体上也是那些东西,没有了X.Y坐标轴,也就没有了第二坐标,要简单一点.PieChartControl.xaml <UserControl x:Class ...
- LiteOS的内核——RTOS基本的特性
在其他的rtos中,基本上也有类似的功能,ucos freertos,要是rtos的时候,务必选择自带的rtos功能,和裸机运行时有区别的
- Java进阶知识08 Hibernate多对一单向关联(Annotation+XML实现)
1.Annotation 注解版 1.1.在多的一方加外键 1.2.创建Customer类和Order类 package com.shore.model; import javax.persisten ...
- [Luogu] Mayan游戏
https://www.luogu.org/problemnew/show/P1312 太恶心了 #include <cstdio> #include <algorithm> ...
- [JSOI 2016] 最佳团体(树形背包+01分数规划)
4753: [Jsoi2016]最佳团体 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2003 Solved: 790[Submit][Statu ...
- 在linux操作系统上进行简单的C语言源码的gcc编译实验
尝试在linux上用gcc 而非封装完好的codeblocks,vs等ide 来编译c和cpp源程序 首先查看我的gcc版本,我的是VM centos 自带的,没有的话得自行安装,安装上gcc就可以在 ...
- C#操作 Access 2013(.accdb)的方法
使用的Microsoft.Jet.OLEDB.4.0,的方法并不能连接最新的Access 存储文件,而且Microsoft.Jet.OLEDB.4.0不能使用x64的方式生成,而且使用这个数据库引擎效 ...