Django: Пример общих отношений с использованием структуры contenttypes?
Я несколько раз просматривал документы Django в отношении структуры contenttypes, и я просто недостаточно понимаю это, чтобы реализовать общие отношения в моем проекте. Я искал онлайн-примеры или учебники по этому вопросу, но я не могу найти ни одного. Назовите меня глупым, но мне нужна помощь в этом (пожалуйста, не отвечайте, просто связавшись с документами). Основываясь на нехватке ресурсов в Интернете, я верю, что если вы ответите на этот вопрос с помощью тщательного примера, ваш ответ может быть самым полезным примером онлайн на сегодняшний день в отношении общих отношений django (бонус!).
Итак, мой вопрос: может ли кто-нибудь показать простой пример моделей и, возможно, пару строк кода, показывающих, как взаимодействовать с экземплярами универсальной модели?
Как вдохновение, вот что я считаю очень распространенной ситуацией:
У сайта есть медиа-элементы, которые в основном обрабатываются одинаково, но немного отличаются. Например, скажем, есть изображения и видеоматериалы, и пользователи могут "любить" элемент или "комментировать" по элементу. К подобным и комментариям следует относиться одинаково, независимо от того, размещены ли они на изображении или элементе видео. Итак, если в пользовательском альбоме есть ItemView для просмотра изображения или видео, возможны следующие виды вызовов: mediaitem.comments.all()
или len(mediaitem.likes.all())
или comment.user_who_commented
, не зная, какой вид медиа-элемента он (изображение или видео).
Я полагаю, вам понадобится шесть моделей для этого:
- Абстрактный
MediaItem
класс
- Два разных типа элементов мультимедиа:
ImageItem
и VideoItem
- Абстрактный
MediaItemActions
класс
- Два разных типа действий, которые могут быть сделаны в отношении элементов мультимедиа:
Like
и Comment
Если вы знаете, как использовать эту функцию Django, пожалуйста, покажите нам полный пример! Я чувствую, что это будет чрезвычайно мощный инструмент, и я боюсь использовать его в своем приложении. Чем яснее, тем лучше.
Ответы
Ответ 1
Ваш случай использования звучит очень похоже на (теперь устаревший) рамки комментариев Django. Если вы посмотрите models, вы увидите, как использовать общее отношение в BaseCommentAbstractModel
- обратите внимание, что вам нужны все три полей, от ForeignKey
до ContentType
, поля для хранения объектов pk
s и поля GenericForeignKey
.
Что касается запросов к объектам с помощью GenericForeignKey
, вы можете увидеть несколько примеров в тегах в этом проекте. См., Например, метод get_query_set
в BaseCommentNode
, который извлекает комментарии, запрашивая тип содержимого и pk целевого объекта.
def get_query_set(self, context):
ctype, object_pk = self.get_target_ctype_pk(context)
if not object_pk:
return self.comment_model.objects.none()
qs = self.comment_model.objects.filter(
content_type = ctype,
object_pk = smart_text(object_pk),
site__pk = settings.SITE_ID,
)
Ответ 2
На самом деле у меня очень похожая ситуация в одном из моих проектов с различными типами носителей.
class TaggedItem(models.Model):
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class ReviewedItem(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
review = models.ForeignKey("Review")
class CreativeWork(models.Model):
#other fields
keywords = generic.GenericRelation("TaggedItem",null=True, blank=True, default=None)
reviews = generic.GenericRelation("ReviewedItem",null=True, blank=True, default=None)
class MediaObject(CreativeWork):
#fields
class VideoObject(MediaObject):
#fields
class AudioObject(MediaObject):
#fields
Каждое видео или аудио - это объект MediaObject, который представляет собой CreativeWork.
CreativeWorks имеет GenericRelation для тегов и обзоров. Итак, теперь все может быть помечено или просмотрено.
Все, что вам нужно, это "действие", чтобы иметь ForeignKey в ContentType.
Затем добавьте GenericRelation в вашу модель. Я действительно нашел django.docs очень полезным:)
Но если не надеюсь, что это поможет.
Ответ 3
Другим вариантом является Полиморфные модели. Я не скажу, что так вы должны идти, но это может быть вариант.
Я поклонник как общих внешних ключей, так и полиморфных моделей. Полиморфные модели лучше всего работают в тех сценариях, где в моделях много сходства.