Django内容类型究竟如何工作?

我真的很难把握Django内容类型的概念。 它感觉非常黑客,并最终反对Python如何处理事情。 话虽如此,如果我要使用Django,那么我必须在框架的范围内工作。

所以我来这里想知道是否有人可以给出一个实用的真实世界的例子,说明内容类型是如何工作的以及如何实现它。 几乎所有我所查阅的教程(主要是在博客上)都没有真正涵盖这个概念。 他们似乎拿起Django文档离开的地方(似乎没有任何地方)。


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

首先问自己这个问题:“这些模型中的任何一个模型都需要与其他模型以相同的方式关联起来,并且/或者我会在未来的道路上以未知的方式重用这些关系吗?” 我们问这个问题的原因是因为这是内容类型框架最擅长的:它在模型之间创建通用关系。 Blah blah,让我们深入一些代码,看看我的意思。

# 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和一个用于object_idPositiveIntegerField 。 这些字段用于告诉Django这是什么类型的对象,以及该对象的id是什么。 实际上,这是有道理的,因为Django需要同时查找这些相关的对象。

那么,这不是很像Python ......它有点丑陋!

您可能正在寻找能让Guido van Rossum感到自豪的密封,一尘不染,直观的代码。 我得到你。 让我们看一下GenericRelation字段,这样我们就可以在这个上面打个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

# 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!">]

就这么简单。

这些“通用”关系的其他实际含义是什么?

通用外键允许各种应用程序之间的较少干扰关系。 例如,假设我们将评论模型拉出到它自己的名为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倍。

通用关系(?)要小心!

一个相当大的警告是,当您使用GenericRelation ,如果删除了具有GenericRelationPicture )的模型,则所有相关( Comment )对象也将被删除。 或者至少在撰写本文时。


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

这就是说,它读/允许你修改/传递'Content- type'httpd头部。

但是,您需要更多练习用法示例。 我有2个建议给你:

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社区的力量。 有2个令人敬畏的RESTFul插件Django。 所以如果你想看看整个兔子有多深,你可以退房。

  • Django休息框架
  • tastypie
  • 我建议通过django-rest-framework教程来解决“专门针对不同内容/类型”的问题。 注意:通常的做法是将内容类型头部用于'version'restful API。

    链接地址: http://www.djcxy.com/p/31951.html

    上一篇: How exactly do Django content types work?

    下一篇: How to debug in Django, the good way?