Django内容types究竟如何工作?

我讨厌浪费人们的时间。 这是我在这里的第一篇文章,在广泛search答案的日子之后,这只是最后一招。 我真的很难把握Django内容types的概念。 这感觉非常黑客,并最终反对Python如何去做。 这就是说,如果我要使用Django,那么我必须在框架的范围内工作。

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

我很欣赏你们在这里做的事情,我真的很想看到你们要说的话。

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

首先问自己这个问题:“这些模型中的任何一个模型是否需要和其他模型以相同的方式关联起来,并且/或者我会在未来的路上以不可预知的方式重用这些关系吗? 我们问这个问题的原因是因为这是内容types框架最好的:它创build模型之间的通用关系。 等等,让我们深入一些代码,看看我的意思。

# 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程序员,你的卓越才智正在告诉你这个糟透了,你可以做得更好。 举手击掌!

input内容types框架!

那么现在我们将仔细研究我们的模型,并将它们重新devise为更“可重用”和直观。 我们先从Comment模型中去掉两个外键,然后用GenericForeignKeyreplace它们。

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

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

您可能正在寻找让Guido van Rossum感到自豪的气密,一尘不染,直观的代码。 我得到你。 让我们来看一下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项目目录中inputpython 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!">] 

就这么简单。

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

通用外键允许各种应用程序之间的较less干扰关系。 例如,假设我们将“评论”模型引入自己的名为“ chatterly的应用程序。 现在我们要创build另一个名为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字段的应用。

这真的太好了吗?

和生活中的任何事物一样,有利有弊。 每当你添加更多的代码和更多的抽象,底层的stream程就会变得更沉重,速度更慢。 添加通用关系可以添加一点性能阻尼器,尽pipe它会尝试并智能地caching其结果。 总而言之,清洁度和简单性是否超过微小的性能收益。 对我来说,答案是一百万次是的。

内容types框架比我在这里显示的更多。 有一个完整的粒度和更详细的用法,但是对于一般的个人来说,在我看来,这就是你将如何使用它的10倍。

通用关系(?)要小心!

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

好的,直接回答你的问题:(从Django的源代码)是: 媒体typesparsing根据RFC 2616,第3.7节。

这是说,它读/允许你修改/传递“内容types” httpd标题的眼泪方式。

但是,您正在要求更多练习用法示例。 我有两个build议给你:

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。 所以,如果你想看看整个兔子有多深,你可以检查。

  • Djangorest框架
  • tastypie

我build议通过django-rest-framework教程来解决“专门针对不同内容/types”的问题。 注意:通常的做法是将内容types的头部用于'version'restful API 。