Как именно работают типы контента Django?
Мне действительно трудно понять концепцию типов контента Django. Он чувствует себя очень хакерским и, в конечном счете, против того, как Python имеет тенденцию делать вещи. При этом, если я собираюсь использовать Django, то я должен работать в пределах рамок.
поэтому я прихожу сюда, задаваясь вопросом, Может ли кто-нибудь дать практический реальный пример того, как работает тип контента и как вы его реализуете. Почти все учебники (в основном в блогах), которые я рассмотрел, не сделайте большую работу, действительно охватывая концепцию. Кажется, они поднимают, где документация Django остановилась (что кажется нигде).
2 ответов
Итак, вы хотите использовать фреймворк типов контента в своей работе?
# 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
to ContentType
и PositiveIntegerField
на object_id
. Эти поля предназначены для того, чтобы сообщить Django, с каким типом объекта это связано и какой идентификатор для этого объекта. На самом деле, это имеет смысл, потому что Django понадобится как для поиска этих связанных объекты.
Ну, это не очень в стиле Python... его нелепый!
вы, вероятно, ищете герметичный, безупречный, интуитивно понятный код, который сделает Гвидо ван Россум гордиться. Я тебя понимаю. Давайте посмотрим на 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')
БАМ! Так же, как вы можете работать с комментариями для этих двух моделей. На самом деле, давайте продолжим и сделаем это в нашей оболочке (тип python manage.py shell
из вашего проекта Django справочник.)
>>> 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
поля.
это слишком хорошо, чтобы быть правдой?
как и все в жизни, есть плюсы и минусы. Каждый раз, когда вы добавляете больше кода и больше абстракции, базовые процессы становятся тяжелее и немного медленнее. Добавление общие отношения могут добавить немного демпфера производительности, несмотря на то, что он попытается и смарт-кэшировать свои результаты. В общем, все сводится к тому, перевешивает ли чистота и простота небольшие выигрыши в производительности. Для меня ответ в миллион раз "да".
в структуре типов контента больше, чем я показывал здесь. Существует целый уровень детализации и более подробного использования, но для среднего человека это то, как вы будете использовать его 9 в 10 раз на мой взгляд.
универсальный relationizers(?) будьте осторожны!
довольно большая предостережение это когда вы используете GenericRelation
, если модель, которая имеет GenericRelation
прикладная (Picture
) удаляется, все связанные (Comment
) объекты также будут удалены. Или, по крайней мере, на момент написания этой статьи.
Ok хорошо прямой ответ на ваш вопрос: (из исходного кода 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-rest-framework, который будет касаться "действия на разных контентах/типах". Примечание: общая практика использовать заголовок content-type в "версия" restful API.