Gracefully skip reference indexing for objects with a null ParentalKey

Fixes #9583. The use case for null ParentalKeys is a bit questionable, but if they exist, we don't want reference indexing to break on them. Since references are always stored against the parent object, there's no valid way to record these references, so gracefully skip over them instead.
pull/9610/head
Matt Westcott 2022-11-04 14:17:38 +00:00
rodzic 66f2512ef5
commit a87a5d8d5a
4 zmienionych plików z 72 dodań i 1 usunięć

Wyświetl plik

@ -83,6 +83,9 @@ def update_reference_index_on_save(instance, **kwargs):
break
instance = getattr(instance, parental_keys[0].name)
if instance is None:
# parent is null, so there is no valid object to record references against
return
if ReferenceIndex.model_is_indexable(type(instance)):
with transaction.atomic():

Wyświetl plik

@ -0,0 +1,41 @@
# Generated by Django 4.1.2 on 2022-11-04 14:00
from django.db import migrations, models
import django.db.models.deletion
import modelcluster.fields
import wagtail.fields
class Migration(migrations.Migration):
dependencies = [
("wagtailcore", "0078_referenceindex"),
("tests", "0010_alter_customimage_file_and_more"),
]
operations = [
migrations.CreateModel(
name="ModelWithNullableParentalKey",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("content", wagtail.fields.RichTextField()),
(
"page",
modelcluster.fields.ParentalKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="wagtailcore.page",
),
),
],
),
]

Wyświetl plik

@ -1975,3 +1975,14 @@ class ModelWithStringTypePrimaryKey(models.Model):
custom_id = models.CharField(max_length=255, primary_key=True)
content = models.CharField(max_length=255)
class ModelWithNullableParentalKey(models.Model):
"""
There's not really a valid use case for null parental keys, but their presence should not
break things outright (e.g. when determining the object ID to store things under in the
references index).
"""
page = ParentalKey(Page, blank=True, null=True)
content = RichTextField()

Wyświetl plik

@ -7,7 +7,11 @@ from django.test import TestCase
from wagtail.images import get_image_model
from wagtail.images.tests.utils import get_test_image_file
from wagtail.models import Page, ReferenceIndex
from wagtail.test.testapp.models import EventPage, EventPageCarouselItem
from wagtail.test.testapp.models import (
EventPage,
EventPageCarouselItem,
ModelWithNullableParentalKey,
)
class TestCreateOrUpdateForObject(TestCase):
@ -163,6 +167,18 @@ class TestCreateOrUpdateForObject(TestCase):
self.expected_references,
)
def test_null_parental_key(self):
obj = ModelWithNullableParentalKey(
content="""<p><a linktype="page" id="%d">event page</a></p>"""
% self.event_page.id
)
obj.save()
# Models with a ParentalKey are not considered indexable - references are recorded against the parent model
# instead. Since the ParentalKey is null here, no reference will be recorded.
refs = ReferenceIndex.get_references_to(self.event_page)
self.assertEqual(refs.count(), 0)
def test_rebuild_references_index_no_verbosity(self):
stdout = StringIO()
management.call_command(