РЕПЕТИТОР математика физика информатика
Для школьников и студентов. Подтягивание пробелов. ЦЭ, ЦТ, ОГЭ, ЕГЭ.
Идет набор на ЛЕТО. Жмите для подробностей:)
46 of 818 menu

Поле GenericForeignKey

Поле GenericForeignKey не является стандартным полем базы данных, а представляет собой специальный класс в Django, который реализует универсальную связь между моделями. Оно не сохраняется напрямую в базе данных, а использует два других поля: поле для хранения идентификатора типа контента (ForeignKey на модель ContentType) и поле для хранения первичного ключа целевого объекта. При обращении к такому полю Django автоматически определяет нужную модель и загружает связанный объект.

Синтаксис

from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models class YourModel(models.Model): content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id')

Пример

Рассмотрим создание модели комментариев, которые могут быть привязаны к разным типам объектов (статьям, постам или продуктам):

from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.db import models class Comment(models.Model): text = models.TextField() created_at = models.DateTimeField(auto_now_add=True) content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() class Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() class Product(models.Model): name = models.CharField(max_length=100) price = models.DecimalField(max_digits=10, decimal_places=2)

Пример

Теперь создадим комментарии для разных объектов:

from myapp.models import Article, Post, Product, Comment article = Article.objects.create(title="First article", content="...") post = Post.objects.create(title="First post", content="...") product = Product.objects.create(name="Laptop", price=1000.00) comment1 = Comment.objects.create( text="Great article!", content_object=article ) comment2 = Comment.objects.create( text="Interesting post", content_object=post ) comment3 = Comment.objects.create( text="Nice product", content_object=product ) print(f"Comment 1: {comment1.content_object} - {comment1.text}") print(f"Comment 2: {comment2.content_object} - {comment2.text}") print(f"Comment 3: {comment3.content_object} - {comment3.text}")

Результат выполнения кода:

"Comment 1: Article object (1) - Great article!" "Comment 2: Post object (1) - Interesting post" "Comment 3: Product object (1) - Nice product"

Пример

Получим все комментарии для конкретной статьи:

from myapp.models import Article, Comment from django.contrib.contenttypes.models import ContentType article = Article.objects.get(id=1) article_content_type = ContentType.objects.get_for_model(article) comments = Comment.objects.filter( content_type=article_content_type, object_id=article.id ) for comment in comments: print(f"Comment: {comment.text}")

Результат выполнения кода:

"Comment: Great article!" "Comment: Another great article!"

Пример

Используем обратную связь через поле GenericRelation:

from django.contrib.contenttypes.fields import GenericRelation from django.db import models class Article(models.Model): title = models.CharField(max_length=200) content = models.TextField() comments = GenericRelation('Comment') class Comment(models.Model): text = models.TextField() content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') # Now we can get comments directly from article article = Article.objects.get(id=1) for comment in article.comments.all(): print(comment.text)

Результат выполнения кода:

"Great article!" "Another great article!"

Смотрите также

  • поле GenericRelation,
    которое позволяет создавать обратную универсальную связь
  • класс prefetch_related_objects,
    который используется для оптимизации запросов с универсальными связями
  • класс prefetch_related,
    который применяется для предварительной загрузки связанных объектов
  • класс filter,
    который используется для фильтрации записей в QuerySet
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить