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. 【Python爬虫案例学习】分析Ajax请求并抓取今日头条街拍图片

    1.抓取索引页内容 利用requests请求目标站点,得到索引网页HTML代码,返回结果. from urllib.parse import urlencode from requests.excep ...

  2. day49——圆形头像、定位、z-index、js

    day49 今日内容 圆形头像 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  3. 虚拟机CentOS创建/使用快照

    快照 1.什么是快照 说的直白一点,就是创建一个备份.当执行了不可逆的错误操作后,可以通过快照用来恢复系统 2.创建快照的三种模式 挂载状态下创建快照 开机状态下创建快照 关机状态下创建快照 3.如何 ...

  4. todolist 包含本地存储知识

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. CentOS7安装Grafana(Yum)

    一.概述 Grafana是一个跨平台的开源的分析和可视化工具,可以通过将采集的数据查询然后可视化的展示,并及时通知. 其特点: 丰富的可视化显示插件,包括热图.折线图.饼图,表格等等. 多数据源,支持 ...

  6. git学习笔记 --分支管理策略

    通常,合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息. 如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的comm ...

  7. 21、Cursorを使う

    例: (詳しい内容が後で追加) declare @tempTB table ( PEファンドコード ) ) --1.データ格納用の変数を声明 ) --2.Cursorを声明.内容を定義 declare ...

  8. C# vb .net实现倾斜效果滤镜

    在.net中,如何简单快捷地实现Photoshop滤镜组中的倾斜效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...

  9. EF CodeFirst Dome学习

    创建ConsoleDome控制台应用程序 从NuGet包管理器安装EntityFramework 创建DbContextDome类并继承DbContext public class DbContext ...

  10. Java调用Http/Https接口(4)--HttpClient调用Http/Https接口

    HttpClient是Apache HttpComponents项目下的一个组件,是Commons-HttpClient的升级版,两者api调用写法也很类似.文中所使用到的软件版本:Java 1.8. ...