|
384 | 384 | subject_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) |
385 | 385 | subject_id = models.PositiveIntegerField() |
386 | 386 | subject = GenericForeignKey("subject_content_type", "subject_id") |
| 387 | +
|
| 388 | +- case: django_contrib_contenttypes_generic_prefetch |
| 389 | + installed_apps: |
| 390 | + - django.contrib.contenttypes |
| 391 | + - myapp |
| 392 | + main: | |
| 393 | + from django.contrib.contenttypes.prefetch import GenericPrefetch |
| 394 | + from myapp.models import Bookmark, Animal, TaggedItem |
| 395 | + from typing_extensions import reveal_type |
| 396 | +
|
| 397 | + # Basic GenericPrefetch usage |
| 398 | + prefetch = GenericPrefetch( |
| 399 | + "content_object", [Bookmark.objects.all(), Animal.objects.only("name")] |
| 400 | + ) |
| 401 | + reveal_type(prefetch) # N: Revealed type is "django.contrib.contenttypes.prefetch.GenericPrefetch[Literal['content_object'], builtins.list[django.db.models.query.QuerySet[django.db.models.base.Model, django.db.models.base.Model]], builtins.str]" |
| 402 | +
|
| 403 | + # Using GenericPrefetch with prefetch_related |
| 404 | + qs = TaggedItem.objects.prefetch_related(prefetch).all() |
| 405 | + reveal_type(qs) # N: Revealed type is "django.db.models.query.QuerySet[myapp.models.TaggedItem, myapp.models.TaggedItem]" |
| 406 | +
|
| 407 | + # GenericPrefetch with to_attr |
| 408 | + prefetch_with_attr = GenericPrefetch( |
| 409 | + "content_object", |
| 410 | + [Bookmark.objects.all(), Animal.objects.only("name")], |
| 411 | + to_attr="prefetched_object" |
| 412 | + ) |
| 413 | + qs_with_attr = TaggedItem.objects.prefetch_related(prefetch_with_attr).all() |
| 414 | + reveal_type(qs_with_attr) # N: Revealed type is "django.db.models.query.QuerySet[myapp.models.TaggedItem@AnnotatedWith[TypedDict({'prefetched_object': builtins.list[Any]})], myapp.models.TaggedItem@AnnotatedWith[TypedDict({'prefetched_object': builtins.list[Any]})]]" |
| 415 | + reveal_type(qs_with_attr.get().prefetched_object) # N: Revealed type is "builtins.list[Any]" |
| 416 | +
|
| 417 | + # GenericPrefetch on invalid field (not a GenericForeignKey) |
| 418 | + regular_fk_prefetch = GenericPrefetch( |
| 419 | + "content_type", |
| 420 | + [Bookmark.objects.all(), Animal.objects.only("name")], |
| 421 | + ) |
| 422 | + TaggedItem.objects.prefetch_related(regular_fk_prefetch).all() # E: "content_type" on "TaggedItem" is not a GenericForeignKey, GenericPrefetch can only be used with GenericForeignKey fields [misc] |
| 423 | + regular_field_prefetch = GenericPrefetch( |
| 424 | + "tag", |
| 425 | + [Bookmark.objects.all(), Animal.objects.only("name")], |
| 426 | + ) |
| 427 | + TaggedItem.objects.prefetch_related(regular_field_prefetch).all() # E: "tag" on "TaggedItem" is not a GenericForeignKey, GenericPrefetch can only be used with GenericForeignKey fields [misc] |
| 428 | +
|
| 429 | + files: |
| 430 | + - path: myapp/__init__.py |
| 431 | + - path: myapp/models.py |
| 432 | + content: | |
| 433 | + from django.db import models |
| 434 | + from django.contrib.contenttypes.models import ContentType |
| 435 | + from django.contrib.contenttypes.fields import GenericForeignKey |
| 436 | +
|
| 437 | + class Bookmark(models.Model): |
| 438 | + url = models.URLField() |
| 439 | +
|
| 440 | + class Animal(models.Model): |
| 441 | + name = models.CharField(max_length=100) |
| 442 | +
|
| 443 | + class TaggedItem(models.Model): |
| 444 | + tag = models.CharField(max_length=100) |
| 445 | + content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) |
| 446 | + object_id = models.PositiveIntegerField() |
| 447 | + content_object = GenericForeignKey('content_type', 'object_id') |
| 448 | +
|
| 449 | +
|
| 450 | +- case: uninstalled_django_contrib_contenttypes_generic_prefetch |
| 451 | + installed_apps: |
| 452 | + - myapp |
| 453 | + main: | |
| 454 | + from django.contrib.contenttypes.prefetch import GenericPrefetch |
| 455 | + from myapp.models import Bookmark, Animal, TaggedItem |
| 456 | + from typing_extensions import reveal_type |
| 457 | +
|
| 458 | + # Basic GenericPrefetch usage |
| 459 | + prefetch = GenericPrefetch( |
| 460 | + "content_object", [Bookmark.objects.all(), Animal.objects.only("name")] |
| 461 | + ) |
| 462 | + reveal_type(prefetch) # N: Revealed type is "django.contrib.contenttypes.prefetch.GenericPrefetch[Literal['content_object'], builtins.list[django.db.models.query.QuerySet[django.db.models.base.Model, django.db.models.base.Model]], builtins.str]" |
| 463 | +
|
| 464 | + # Using GenericPrefetch with prefetch_related |
| 465 | + qs = TaggedItem.objects.prefetch_related(prefetch).all() # E: Cannot find "content_object" on "TaggedItem" object, "content_object" is an invalid parameter to "prefetch_related()" [misc] |
| 466 | + reveal_type(qs) # N: Revealed type is "django.db.models.query.QuerySet[myapp.models.TaggedItem, myapp.models.TaggedItem]" |
| 467 | +
|
| 468 | +
|
| 469 | + files: |
| 470 | + - path: myapp/__init__.py |
| 471 | + - path: myapp/models.py |
| 472 | + content: | |
| 473 | + from django.db import models |
| 474 | +
|
| 475 | + class Bookmark(models.Model): |
| 476 | + url = models.URLField() |
| 477 | +
|
| 478 | + class Animal(models.Model): |
| 479 | + name = models.CharField(max_length=100) |
| 480 | +
|
| 481 | + class TaggedItem(models.Model): |
| 482 | + tag = models.CharField(max_length=100) |
0 commit comments