Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation)。不过由于其非常抽象,

理解起来并不容易。当你创建一个django项目的时候,可以看到在默认的INSTALL_APPS已经包含了django.contrib.contenttypes。

今天我们来重点讲下它的使用场景及如何使用django contenttypes。

# Application definition

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
]

Django ContentTypes框架使用场景

假设我们创建了如下模型,里面包含文章Post,Picture和评论Comment模型。

Comment可以是对Post的评论,也可以是对Picture的评论。

如果你还想对其它对象(比如回答,用户) 进行评论, 这样你将需要在comment对象里添加非常多的ForeignKey。

你的直觉会告诉你,这样做很傻,会造成代码重复和字段浪费。一个更好的方式是,只有当你需要对某个对象或模型进行评论时,

才创建comment与那个模型的关系。这时你就需要使用django contenttypes了。

from django.db import models
from django.contrib.auth.models import User # Create your models here. class Post(models.Model):
   author = models.ForeignKey(User)
   title = models.CharField(max_length=75)
   body = models.TextField(blank=True) class Picture(models.Model):
   author = models.ForeignKey(User)
   image = models.ImageField()
   caption = models.TextField(blank=True) class Comment(models.Model):
   author = models.ForeignKey(User)
   body = models.TextField(blank=True)
   post = models.ForeignKey(Post, null=True)
   picture = models.ForeignKey(Picture, null=True)

Django ContentType提供了一种GenericForeignKey的类型,通过这种类型可以指定content_object。修改过的comment模型如下图所示:

 import ContentType
import GenericForeignKey class Comment(models.Model):
author = models.ForeignKey(User)
body = models.TextField(blank=True) content_type = models.ForeignKey(ContentType)

object_id = models.PositiveIntegerField()
content_object = GenericForeignKey(content_type,object_id)

comment里加了3个字段:

  • content_type: 内容类型,代表了模型的名字(比如Post, Picture)

  • object_id: 传入对象的id

  • content_object: 传入的实例化对象,其包含两个属性content_type和object_id。

当你需要对某篇文章或某个图片进行评论时(建立评论关系),

你只需要将实例化的对象user, post或picture传入comment。

这样实现了按需建立评论关系。首先你先需要实例化对象。

user = User.objects.create_user(username='user1', password='')
post = Post.objects.create(author=user,
                          title='title1',
                          body='')
picture = Picture.objects.create(author=user,
                                image="default.png",
                                caption='picture1')

然后在views或者shell里,你可以按如下代码建立评论关系。

 
 from foreign.models import Post, Picture, Common
>>> from django.contrib.auth.models import User
>>> user = User.objects.get(username='user1')
>>> post = Post.objects.get(title='title1')
>>> c = Comment.objects.create(author=user, body='', content_object=post)
>>> picture = Picture.objects.get(caption='picuture1')
>>> c1 = Comment.objects.create(author=user, body='', content_object=picture)

然而上述创建评论的方式我们并不推荐。

我们更希望直接从模型中获取或创建comment,

我们只需在模型中创建一个与Comment的GenericRelation即可。

注意该字段不会存储于数据库中。

from django.contrib.contenttypes.fields import GenericRelation

class Post(models.Model):
 author = models.ForeignKey(User)
 title = models.CharField(max_length=75)
 body = models.TextField(blank=True)
 comments = GenericRelation('Comment') class Picture(models.Model):
 author = models.ForeignKey(User)
 image = models.ImageField()
 caption = models.TextField(blank=True)
 comments = GenericRelation('Comment')
>>> me = User.objects.get(username='myusername')
>>> pic = Picture.objects.get(author=me)
>>> pic.comments.create(author=me, body="Man, I'm cool!")
>>> pic.comments.all()[<Comment: "Man, I'm cool!">]

值得注意的是,如果在Post中定义了GenericRelation,删除了一个post实例,

在Comment中所有与post相关实例也会被删除。GenericForeignKey不支持设置on_delete参数。

因此,如果对级联删除不满意的话就不要设置GenericRelation。

Django ContentTypes框架使用场景的更多相关文章

  1. Django contenttypes 框架详解

    一.什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Django驱动的model提供了更高层次的抽象 ...

  2. django内置 Contenttypes 框架

    一.什么是Django ContentTypes? 1.Django 包含一个ContentTypes 应用,它可以追踪安装在你的Django 项目里的所有应用,并提供一个高层次的.通用的接口用于与你 ...

  3. Django contenttypes 应用

    Django contenttypes 应用 什么是Django ContentTypes? Django ContentTypes是由Django框架提供的一个核心功能,它对当前项目中所有基于Dja ...

  4. Linux(CentOS7)系统中部署Django web框架

    1. 概述 部署django和vue架在逻辑上可以分为web层与数据库层:web前端通过实现了WSGI协议的模块对python代码进行解析,而python代码中则通过特定于数据库的操作接口对数据库进行 ...

  5. 路飞学城知识点4之Django contenttypes 应用

    Django contenttypes 应用 contenttypes 是Django内置的一个应用,可以追踪项目中所有app和model的对应关系,并记录在ContentType表中. 每当我们创建 ...

  6. Django+Celery框架自动化定时任务开发

    本章介绍使用DjCelery即Django+Celery框架开发定时任务功能,在Autotestplat平台上实现单一接口自动化测试脚本.业务场景接口自动化测试脚本.App自动化测试脚本.Web自动化 ...

  7. 记Angular与Django REST框架的一次合作(1):分离 or 不分离,it's the question

    前言:本次尝试源于我们内部的一个项目,由于前端逻辑比较复杂,就打算将前后端分开来开发.由于之前用Django开发过软件,对Angular.js(Angular 1.0版)也有一定的了解,因此就将技术路 ...

  8. 记Angular与Django REST框架的一次合作(2):前端组件化——Angular

    注:这是这个系列的第二部分,主要集中在Angular的使用方面.之前使用过AngularJS(Angular 1.x),混在Django的模板中使用,这些页面一般完全是结果展示页.在有Django表单 ...

  9. 教程:Visual Studio 中的 Django Web 框架入门

    教程:Visual Studio 中的 Django Web 框架入门 Django 是高级 Python 框架,用于快速.安全及可扩展的 Web 开发. 本教程将在 Visual Studio 提供 ...

随机推荐

  1. Java基础教程(26)--反射

    一.类   对于每一种类型的对象,Java虚拟机都会实例化一个java.lang.Class类的不可变实例.该实例提供了获取对象的运行时属性的方法,包括它的成员和类型信息.Class类还提供了创建新实 ...

  2. Python之路【第二十九篇】:django ORM模型层

    ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人员的 ...

  3. LeetCode 5071. 找出所有行中最小公共元素(Java)

    题目:5071. 找出所有行中最小公共元素 给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1 ...

  4. hadoop2.x大数据视频教程(十二天学会)

  5. php的json_encode第二个参数学习及应用

    php5.4以上: json_encode($data, JSON_FORCE_OBJECT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); p ...

  6. 【简解】SP7556 Stock Charts

    题目大意 给出一个折线图,有N条线段,你想要把这些线段分成几个集合,使得每个集合中任意两条线段不相交. 求最少集合数. 分析 喵帕斯:以下提及的所有折线均指横坐标在\([1,k]\)里的折线段. 思考 ...

  7. mysql执行顺序与join连接

    mysql加载顺序 手写顺序 SELECT DISTINCT <select list> FROM <left_table> join <join_type> JO ...

  8. js-Date对象(九)

    一.Date对象的创建1.new Date()[创建当前时间对象]eg: var date = new Date(); console.log(date); //Thu Jul 18 2019 18: ...

  9. Linux E667 同步失败

    在使用Vim编辑/proc目录下的文件后,保存,显示"E667 同步失败" 原因 因为proc这个目录是一个虚拟文件系统,它放置的数据都是在内存中,本身不占有磁盘空间,所以使用Vi ...

  10. Celery:routing

    参考:http://docs.celeryproject.org/en/latest/userguide/routing.html#guide-routing