Django 内容类型到底是如何工作的?

我真的很难理解 Django 的内容类型的概念。它让人感觉非常恶意,而且最终与 Python 的做事方式背道而驰。也就是说,如果我要使用 Django,那么我必须在框架的范围内工作。

所以我来这里想知道是否有人能够给出一个实际的例子来说明内容类型是如何工作的,以及如何实现它。我评论的几乎所有教程(大部分是在博客上)都没有很好地涵盖这个概念。他们似乎从 Django 文档中断的地方重新开始(似乎什么地方都没有)。

47998 次浏览

好吧,对于您的问题的直接答案是: (来自 django 源代码) : 根据 RFC 2616第3.7节解析媒体类型。

也就是说,它沿着 「内容类型」 httpd 头读取/允许您修改/传递。

但是,你需要一个更实际的使用例子,我有两个建议给你:

1: 检查这个代码

def index(request):
media_type='text/html'
if request.META.has_key('CONTENT_TYPE'):
media_type = request.META['CONTENT_TYPE'].split(';')[0]


if media_type.lower() == 'application/json':
return HttpResponse("""{ "ResponseCode": "Success"}""", content_type="application/json; charset=UTF-8")


return HttpResponse("<h1>regular old joe</h1>");

2: 记住 django 是 python,因此它具有 python 社区的力量。 Django 有两个很棒的 RESTFull 插件。所以如果你想看看兔子有多深你可以去看看。

我建议阅读 django-rest-Framework 教程,该教程将专门讨论“处理不同的内容/类型”。 注意: 在 ‘ version’restful API 的中使用内容类型头是一种常见的做法。

所以你想在你的工作中使用内容类型框架?

从问自己这个问题开始: “这些模型中的任何一个是否需要以同样的方式与其他模型相关联,或者我以后会以不可预见的方式重复使用这些关系?”我们问这个问题的原因是因为这是内容类型框架最擅长的: 它在模型之间创建通用关系。让我们深入一些代码,看看我的意思是什么。

# ourapp.models
from django.conf import settings
from django.db import models


# Assign the User model in case it has been "swapped"
User = settings.AUTH_USER_MODEL


# Create your models here
class Post(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=75)
slug = models.SlugField(unique=True)
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)
picture = models.ForeignKey(Picture)

好吧,理论上我们确实有办法建立这种关系。然而,作为一个 Python 程序员,您的超级智慧告诉您这很糟糕,您可以做得更好。击掌!

输入内容类型框架!

好了,现在我们要仔细看看我们的模型,并重新工作,使它们更加“可重用”和直观。让我们从去掉 Comment模型上的两个外键开始,并用 GenericForeignKey代替它们。

# ourapp.models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType


...


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()

到底发生了什么?好的,我们进入并添加了必要的代码,以允许与其他模型的通用关系。注意这里不仅有一个 GenericForeignKey,而且还有一个 ForeignKeyContentType和一个 PositiveIntegerFieldobject_id。这些字段用于告诉 Django 这与什么类型的对象有关,以及该对象的 id 是什么。实际上,这是有意义的,因为 Django 需要两者来查找这些相关对象。

这可不像蟒蛇,有点丑!

您可能正在寻找无懈可击,一尘不染,直观的代码,这将使 吉多·范罗苏姆感到自豪。我懂你。让我们看看 GenericRelation领域,这样我们就可以在这上面打一个漂亮的蝴蝶结。

# ourapp.models
from django.contrib.contenttypes.fields import GenericRelation


...


class Post(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=75)
slug = models.SlugField(unique=True)
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')

砰!就像这样,你可以使用这两个模型的注释。实际上,让我们在 shell 中继续这样做(在 Django 项目目录中键入 python manage.py shell)。

>>> from django.contrib.auth import get_user_model
>>> from ourapp.models import Picture, Post


# We use get_user_model() since we are referencing directly
User = get_user_model()


# Grab our own User object
>>> me = User.objects.get(username='myusername')


# Grab the first of our own pictures so we can comment on it
>>> pic = Picture.objects.get(author=me)


# Let's start making a comment for our own picture
>>> pic.comments.create(author=me, body="Man, I'm cool!")


# Let's go ahead and retrieve the comments for this picture now
>>> pic.comments.all()
[<Comment: "Man, I'm cool!">]


# Same for Post comments
>>> post = Post.objects.get(author=me)
>>> post.comments.create(author=me, body="So easy to comment now!")
>>> post.comments.all()
[<Comment: "So easy to comment now!"]

就这么简单。

这些“通用”关系还有哪些实际意义?

通用外键允许不同应用程序之间侵入性较小的关系。例如,假设我们将“评论”模型提取到它自己的名为 chatterly的应用程序中。现在,我们想创建另一个名为 noise_nimbus的应用程序,在这个应用程序中,人们可以存储自己的音乐并与他人分享。

如果我们想给这些歌添加评论,那么,我们可以画一个通用的关系:

# noise_nimbus.models
from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models


from chatterly.models import Comment


# For a third time, we take the time to ensure custom Auth isn't overlooked
User = settings.AUTH_USER_MODEL


# Create your models here
class Song(models.Model):
'''
A song which can be commented on.
'''
file = models.FileField()
author = models.ForeignKey(User)
title = models.CharField(max_length=75)
slug = models.SlugField(unique=True)
description = models.TextField(blank=True)
comments = GenericRelation(Comment)

我希望你们发现这有帮助,因为我会喜欢遇到的东西,显示我的更现实的应用程序的 GenericForeignKeyGenericRelation字段。

这是不是好得难以置信?

和生活中的任何事情一样,有利有弊。每当您添加更多的代码和更多的抽象时,底层流程就会变得更加繁重和缓慢。添加通用关系可以增加一点点的性能抑制器,尽管事实上它将尝试和智能缓存其结果。总而言之,这取决于清洁性和简单性是否超过了小的性能成本。对我来说,答案是肯定的。

内容类型框架的内容比我在这里展示的要多。有一个完整的粒度级别和更详细的用法,但对于普通人来说,这是你将如何使用它的10次中的9次,在我看来。

通用关系(?)小心!

一个相当大的 警告是,当您使用 GenericRelation时,如果应用了 GenericRelation的模型(Picture)被删除,所有相关的(Comment)对象也将被删除。或者至少在写这篇文章的时候。