我真的很难掌握Django内容类型的概念。感觉非常hackish,并且最终反对Python倾向于做事情。话虽这么说,如果我要使用Django,那么我必须在框架的范围内工作。
所以我来到这里想知道是否有人能够提供一个实际的现实世界示例,说明内容类型如何工作以及如何实现它。我所评论的几乎所有教程(主要是在博客上)并没有真正涵盖这个概念。他们似乎在Django文档遗留下来的地方(似乎无处可去)。
答案 0 :(得分:259)
首先问自己这个问题:“这些模型中的任何一个是否需要以与其他模型相同的方式相关联和/或我将在未来的时间里以不可预知的方式重复使用这些关系?”我们之所以提出这个问题是因为这就是内容类型框架最擅长的:它创建了模型之间的通用关系。 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
不仅仅是ForeignKey
,还有ContentType
到PositiveIntegerField
和object_id
。这些字段用于告诉Django与此对象相关的对象类型以及该对象的id是什么。实际上,这是有道理的,因为Django将需要两者来查找这些相关的对象。
你可能正在寻找能让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')
的Bam!就像那样,你可以使用这两个模型的评论。实际上,让我们继续在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)
我希望你们发现这很有帮助,因为我喜欢看到一些能够让我更真实地应用GenericForeignKey
和GenericRelation
字段的内容。
与生活中的任何事物一样,有利有弊。无论何时添加更多代码和更多抽象,底层进程都会变得更重,速度更慢。添加泛型关系可以增加一点性能阻尼,尽管它会尝试并智能缓存其结果。总而言之,它归结为清洁度和简洁性是否超过了小的性能成本。对我来说,答案是百万次是的。
内容类型框架比我在此处显示的更多。有一个完整的粒度级别和更详细的使用,但对于普通人来说,这就是我认为你将在10次中使用它的方式。
相当大的警告是当您使用GenericRelation
时,如果已删除已应用GenericRelation
的模型(Picture
),则所有相关(Comment
)对象也将被删除。或者至少截至撰写本文时为止。
答案 1 :(得分:-1)
好的直接回答你的问题:(来自django源代码)是: Media Types parsing according to RFC 2616, section 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社区的力量。 django有2个很棒的RESTFul插件。所以,如果你想看看整个兔子有多深,你可以看看。
我建议仔细阅读django-rest-framework教程,该教程将专门针对“不同内容/类型”。 注意:通常的做法是使用内容类型标题'version' restful API's。