Fix handling of generic foreign keys in reference index

Fix two bugs with the handling of generic foreign keys within `ReferenceIndex._extract_references_from_object`:

* null values were not considered
* content type ID was copied directly from the source field, unlike all other cases that translate to the base content type instead - lookups use the base content type, so these results were not returned.

Fixes #9615
pull/9610/head
Matt Westcott 2022-11-07 16:29:49 +00:00
rodzic a87a5d8d5a
commit 0534f74002
4 zmienionych plików z 54 dodań i 5 usunięć

Wyświetl plik

@ -265,10 +265,15 @@ class ReferenceIndex(models.Model):
if isinstance(field, GenericForeignKey):
ct_field = object._meta.get_field(field.ct_field)
fk_field = object._meta.get_field(field.fk_field)
ct_value = ct_field.value_from_object(object)
fk_value = fk_field.value_from_object(object)
if ct_value is not None and fk_value is not None:
model = ContentType.objects.get_for_id(ct_value).model_class()
yield cls._get_base_content_type(model).id, str(
fk_value
), field.name, field.name
yield ct_field.value_from_object(object), str(
fk_field.value_from_object(object)
), field.name, field.name
continue
if isinstance(field, GenericRel):

Wyświetl plik

@ -0,0 +1,30 @@
# Generated by Django 4.1.2 on 2022-11-07 16:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("tests", "0011_modelwithnullableparentalkey"),
]
operations = [
migrations.AlterField(
model_name="genericsnippetpage",
name="snippet_content_type",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="contenttypes.contenttype",
),
),
migrations.AlterField(
model_name="genericsnippetpage",
name="snippet_object_id",
field=models.PositiveIntegerField(blank=True, null=True),
),
]

Wyświetl plik

@ -1567,9 +1567,9 @@ class GenericSnippetPage(Page):
"""
snippet_content_type = models.ForeignKey(
ContentType, on_delete=models.SET_NULL, null=True
ContentType, on_delete=models.SET_NULL, null=True, blank=True
)
snippet_object_id = models.PositiveIntegerField(null=True)
snippet_object_id = models.PositiveIntegerField(null=True, blank=True)
snippet_content_object = GenericForeignKey(
"snippet_content_type", "snippet_object_id"
)

Wyświetl plik

@ -10,6 +10,7 @@ from wagtail.models import Page, ReferenceIndex
from wagtail.test.testapp.models import (
EventPage,
EventPageCarouselItem,
GenericSnippetPage,
ModelWithNullableParentalKey,
)
@ -179,6 +180,19 @@ class TestCreateOrUpdateForObject(TestCase):
refs = ReferenceIndex.get_references_to(self.event_page)
self.assertEqual(refs.count(), 0)
def test_generic_foreign_key(self):
page1 = GenericSnippetPage(
title="generic snippet page", snippet_content_object=self.event_page
)
self.root_page.add_child(instance=page1)
page2 = GenericSnippetPage(
title="generic snippet page", snippet_content_object=None
)
self.root_page.add_child(instance=page2)
refs = ReferenceIndex.get_references_to(self.event_page)
self.assertEqual(refs.count(), 1)
def test_rebuild_references_index_no_verbosity(self):
stdout = StringIO()
management.call_command(