Поле GenericRelation
Поле GenericRelation применяется на модели, которая выступает в роли цели для универсальной связи. Оно позволяет получить все объекты связанной модели, ссылающиеся на текущую запись через GenericForeignKey. Это поле объявляется в модели как атрибут класса и принимает как минимум один обязательный аргумент - модель, с которой устанавливается обратная связь. Доступ к связанным объектам осуществляется через менеджер этого поля, который ведёт себя аналогично менеджеру ForeignKey.
Синтаксис
from django.contrib.contenttypes.fields import GenericRelation
from django.db import models
class TargetModel(models.Model):
related_objects = GenericRelation('SourceModel')
Пример
Рассмотрим классический пример с моделью Tag, которая может быть связана с разными моделями (статьями и пользователями). Для обратной связи создадим модели Article и UserProfile с полем GenericRelation:
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
class Tag(models.Model):
name = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
tags = GenericRelation(Tag)
def __str__(self):
return self.title
class UserProfile(models.Model):
username = models.CharField(max_length=100)
bio = models.TextField()
tags = GenericRelation(Tag)
def __str__(self):
return self.username
Теперь создадим несколько тегов для статьи и получим их через обратную связь:
from myapp.models import Article, Tag, UserProfile
# Создаем статью и теги для неё
article = Article.objects.create(title="My Article", content="Content")
tag1 = Tag.objects.create(name="Python", content_object=article)
tag2 = Tag.objects.create(name="Django", content_object=article)
# Получаем теги через обратную связь
res = article.tags.all()
for tag in res:
print(tag.name)
Результат выполнения кода:
"Python"
"Django"
Пример
Используем GenericRelation для фильтрации и создания связанных объектов. Получим все теги, принадлежащие профилям пользователей:
from myapp.models import Article, Tag, UserProfile
# Создаем профили пользователей с тегами
profile1 = UserProfile.objects.create(username="alice", bio="Developer")
profile2 = UserProfile.objects.create(username="bob", bio="Designer")
Tag.objects.create(name="Developer", content_object=profile1)
Tag.objects.create(name="Designer", content_object=profile2)
# Фильтруем теги через обратную связь
res = UserProfile.objects.filter(tags__name="Developer")
for profile in res:
print(profile.username)
Результат выполнения кода:
"alice"
Пример
С помощью GenericRelation можно также добавлять и удалять связанные объекты. Добавим новый тег к статье:
from myapp.models import Article, Tag
article = Article.objects.get(title="My Article")
new_tag = Tag.objects.create(name="Web")
# Добавляем тег к статье
article.tags.add(new_tag)
res = article.tags.all()
for tag in res:
print(tag.name)
Результат выполнения кода:
"Python"
"Django"
"Web"
Смотрите также
-
поле
GenericForeignKey,
которое создаёт универсальную связь с любой моделью -
поле
ForeignKey,
которое создаёт связь «один ко многим» с конкретной моделью -
поле
ManyToManyField,
которое создаёт связь «многие ко многим» с конкретной моделью -
поле
OneToOneField,
которое создаёт связь «один к одному» с конкретной моделью