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下的具体的模型类的名称。

应用场景

我们在网上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()

原文地址:https://www.cnblogs.com/niuli1987/p/10282488.html

时间: 2024-10-13 00:35:30

django -- contenttypes组件的相关文章

8.12 Django contenttypes组件

contenttypes组件 介绍 Django包含一个contenttypes应用程序(app),可以跟踪Django项目中安装的所有模型(Model),提供用于处理模型的高级通用接口. Contenttypes应用的核心是ContentType模型,位于django.contrib.contenttypes.models.ContentType. ContentType的实例表示并保存项目中安装的模型的信息,每当有新的模型时会自动创建新的ContentType实例. 只要使用django-a

Django ==> Form 组件

Django ==> Form 组件 目录: 1.基本使用 2.form中字段和插件 3.自定义验证规则 4.动态加载数据到form中 Action: 1.基本使用 django 中的Form组件有一下功能: 1.生成html标签 2.验证用户数据(显示错误信息) 3.html form 提交保留上次提交数据 4.初始化页面显示内容 要使用 form 类,首先需要创建这个类,方法如下: from django.forms import Form from django.forms import

Django contenttypes 框架详解

一.什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象接口. 当然我们不是说的是http中的content-type!完全没有任何关系!下面将一步一步解释Django ContentTypes在Django框架中做了什么,以及如何使用Django ContentTypes. 当然,如果对于ContentTypes有了初步了解而只是不了解它的应用场景,可

Django forms组件【对form舒心l了】

目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段,不渲染它 form 校验 form类 ModelForm 利用ModelForm关键就在于model's field mapping to form's field ModelForm.save() 详解 class Meta !!!重写覆盖默认的modelField字段(即自定义一些modelform属性) form有关多选择Field的使用 form's fi

Django框架(十五)—— Django分页组件

Django分页组件 一.分页器 数据量大的话,可以分页获取,查看 例如:图书管理中,如果有成千上万本书,要是都在一个页面中渲染出来,会影响页面美观,所以就要用分页器分页渲染 二.分页器的使用 基本写法 基本写法: 后端: 总数据拿出来 生成分页器Paginator对象(对象里有属性和方法) 生成当前页的对象,current_page=paginator.page(当前页码) 取出前台传过来的页码,current_page_num = int(request.GET.get('page')) -

django -----分页器组件

1 Django的分页器(paginator)简介 2 应用View层 3 模版层 index.html 4 扩展 回到目录 1 Django的分页器(paginator)简介 在页面显示分页数据,需要用到Django分页器组件 from django.core.paginator import Paginator Paginator对象: paginator = Paginator(user_list, 10) # per_page: 每页显示条目数量 # count: 数据总个数 # num

Django——forms 组件

一.forms简介 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确.如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.. Django forms组件主要功能: 生成页面可用的HTML标签 对用户提交的 数据进行校验 保留上次输入的内容 二.如何使用Django forms 1.注册功能: 渲染前端标签获取用

17 Django Form组件

目录 一.Form 介绍 二.注册功能校验数据案例 1.普通方式手写注册功能 2. 使用Form组件实现注册功能校验数据 三.Form组件如何校验数据 四.Form组件如何渲染前端页面 方式一: 方式二: 方式三: 五.Form组件如何展示错误信息 六.Form组件 参数 七.Form组件 钩子函数 1. 局部钩子函数 2. 全局钩子函数 一.Form 介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多

Django ContentTypes框架使用场景

Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation).不过由于其非常抽象, 理解起来并不容易.当你创建一个django项目的时候,可以看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes. 今天我们来重点讲下它的使用场景及如何使用django contenttypes. # Application definition INSTALLED_APPS = [ 'django.co