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. 对javascript中call()方法的理解

    call ( thisObj [, arg1 [, arg2 [,  [, argN] ] ] ]) call()方法:官方介绍是,调用一个对象的一个方法,以另一个对象替换当前对象. call()方法 ...

  2. vs 远程调试

    程序在vs安装目录: D:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\Remote Debugge ...

  3. javascript应该嵌入到html中的什么位置

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

  4. k8s 运行应用

    一.deployment 创建过程 kubect创建deployment —> deployment 创建ReplicaSet—>根据ReplicaSet 创建Pod 命名方式 relic ...

  5. springcolud 的学习(一),架构的发展史

    一.传统架构 传统的SSH架构,分为三层架构 web控制层.业务逻辑层.数据库访问层. 传统架构也就是单点应用,就是大家在刚开始初学JavaEE技术的时候SSH架构或者SSM架构,业务没有进行拆分,都 ...

  6. Win10家庭版升级到企业版的方法

    一.家庭版升级企业版 1.右键单击[此电脑]——>属性 2.点击更改产品密钥 3.输入密钥:NPPR9-FWDCX-D2C8J-H872K-2YT43 4.点击下一步,验证结束后点击开始升级,然 ...

  7. Source roots (or source folders) Test source roots (or test source folders; shown as rootTest)Resource rootsTest resource roots

    idea中Mark Directory As里的Sources Root.ReSources Root等的区别 1.Source roots (or source folders) 通过这个类指定一个 ...

  8. MSP---助力企业轻松上云

    一.企业上云的总体步骤 1.传统企业级应用上云方法论概述 2.应用现代化概念 3.应用上云都需要什么 1.评估该应用是否可以上云, 2.上云需要付出多少时间和人力 3.企业级应用案例 4.生成评估报告 ...

  9. Error creating bean with name 'XXX' defined in file

    这个错误是我在之前操作时,错将另一个dubbo服务器也加载到了该dubbo服务器上(pom.xml),所以出现了Error creating bean with name 'XXX' defined ...

  10. 关于justify-content属性的再学习(区分三个属性)

    justify-content属性: 用来表示可伸缩项目在主轴方向上的对齐方式: 取值范围为flex-start,flex-end,center,space-between,space-around: ...