Подтвердить что ты не робот

Как конкретно работают типы контента Django?

Мне действительно сложно усвоить концепцию типов контента Django. Он чувствует себя очень хакерским и, в конечном счете, против того, как Python стремится делать что-то. При этом, если я собираюсь использовать Django, тогда мне нужно работать в рамках рамки.

Итак, я прихожу сюда, интересно, может ли кто-нибудь дать практический реальный пример того, как работает тип контента и как вы его реализуете. Почти все учебники (в основном на блогах), которые я рассмотрел, не делают отличную работу, которая действительно охватывает концепцию. Они, похоже, забирают, где документация Django прекратилась (что ни к чему не похоже).

4b9b3361

Ответ 1

Итак, вы хотите использовать инфраструктуру типов контента в своей работе?

Начните с того, что задайте себе вопрос: "Должны ли какие-либо из этих моделей быть связаны таким же образом с другими моделями, и/или я буду использовать эти отношения непредвиденными способами позже в будущем?" Причина, по которой мы задаем этот вопрос, заключается в том, что именно это делает структура типов контента лучше всего: она создает общие отношения между моделями. Бла-бла, давайте погрузимся в некоторый код и посмотрим, что я имею в виду.

# 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 понадобится оба для поиска этих связанных объектов.

Ну, это не очень похоже на 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')

Bam! Точно так же вы можете работать с комментариями для этих двух моделей. На самом деле, давайте продолжим и сделаем это в нашей оболочке (введите 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 start making a comment for our own picture
>>> pic.comments.create(author=me, body="Man, I'm cool!")

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

Это так просто.

Каковы другие практические последствия этих "общих" отношений?

Общие внешние ключи обеспечивают менее навязчивые отношения между различными приложениями. Например, допустим, мы вытащили модель Comment из собственного приложения с именем 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 раз.

Общие реляционеры (?) Будьте осторожны!

Довольно большая оговорка заключается в том, что при использовании GenericRelation, если модель, к которой применен GenericRelation (Picture), будет удалена, все связанные (Comment) объекты также будут удалены., Или, по крайней мере, на момент написания этой статьи.

Ответ 2

Хорошо, что прямой ответ на ваш вопрос: (из исходного кода 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. В django есть 2 удивительных плагина RESTFul. Поэтому, если вы хотите увидеть, насколько глубоко весь кролик идет, вы можете проверить.

Я предлагаю пройти через учебник django-rest-framework, в котором будет рассмотрено "действующее действие на разные контенты/типы". Примечание. Обычно используется заголовок типа контента для 'версии', поддерживающего непринужденный API.