Use an extensible registry for comparison classes

pull/8067/head
Matt Westcott 2021-11-04 19:03:40 +00:00 zatwierdzone przez Matt Westcott
rodzic 3a561aa934
commit 6e34b2fdcc
2 zmienionych plików z 46 dodań i 12 usunięć

Wyświetl plik

@ -1,13 +1,18 @@
import difflib
from bs4 import BeautifulSoup
from django.core.exceptions import ImproperlyConfigured
from django.db import models
from django.utils.encoding import force_str
from django.utils.html import escape, format_html, format_html_join
from django.utils.safestring import mark_safe
from django.utils.text import capfirst
from django.utils.translation import gettext_lazy as _
from taggit.managers import TaggableManager
from wagtail.core import blocks
from wagtail.core.fields import RichTextField
from wagtail.utils.registry import ModelFieldRegistry
def text_from_html(val):
@ -15,6 +20,32 @@ def text_from_html(val):
return BeautifulSoup(force_str(val), "html5lib").getText()
comparison_class_registry = ModelFieldRegistry()
def register_comparison_class(
field_class, to=None, comparison_class=None, exact_class=False
):
"""
Define parameters for form fields to be used by WagtailAdminModelForm for a given
database field.
"""
if comparison_class is None:
raise ImproperlyConfigured(
"register_comparison_class must be passed a 'comparison_class' keyword argument"
)
if to and field_class != models.ForeignKey:
raise ImproperlyConfigured(
"The 'to' argument on register_comparison_class is only valid for ForeignKey fields"
)
comparison_class_registry.register(
field_class, to=to, value=comparison_class, exact_class=exact_class
)
class FieldComparison:
is_field = True
is_child_relation = False
@ -56,6 +87,10 @@ class TextFieldComparison(FieldComparison):
return diff_text(self.val_a, self.val_b).to_html()
register_comparison_class(models.CharField, comparison_class=TextFieldComparison)
register_comparison_class(models.TextField, comparison_class=TextFieldComparison)
class RichTextFieldComparison(TextFieldComparison):
def htmldiff(self):
return diff_text(
@ -63,6 +98,9 @@ class RichTextFieldComparison(TextFieldComparison):
).to_html()
register_comparison_class(RichTextField, comparison_class=RichTextFieldComparison)
def get_comparison_class_for_block(block):
if hasattr(block, "get_comparison_class"):
return block.get_comparison_class()
@ -346,6 +384,9 @@ class TagsFieldComparison(M2MFieldComparison):
return tag.slug
register_comparison_class(TaggableManager, comparison_class=TagsFieldComparison)
class ForeignObjectComparison(FieldComparison):
def get_objects(self):
model = self.field.related_model

Wyświetl plik

@ -7,7 +7,6 @@ from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.core.signals import setting_changed
from django.db.models.fields import CharField, TextField
from django.dispatch import receiver
from django.forms.formsets import DELETION_FIELD_NAME, ORDERING_FIELD_NAME
from django.forms.models import fields_for_model
@ -16,12 +15,10 @@ from django.utils.functional import cached_property
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy
from modelcluster.models import get_serializable_data_for_fields
from taggit.managers import TaggableManager
from wagtail.admin import compare, widgets
from wagtail.admin.forms.comments import CommentForm, CommentReplyForm
from wagtail.admin.templatetags.wagtailadmin_tags import avatar_url, user_display_name
from wagtail.core.fields import RichTextField
from wagtail.core.models import COMMENTS_RELATION_NAME, Page
from wagtail.core.utils import camelcase_to_underscore
from wagtail.utils.decorators import cached_classmethod
@ -550,20 +547,16 @@ class FieldPanel(EditHandler):
if field.choices:
return compare.ChoiceFieldComparison
comparison_class = compare.comparison_class_registry.get(field)
if comparison_class:
return comparison_class
if field.is_relation:
if isinstance(field, TaggableManager):
return compare.TagsFieldComparison
elif field.many_to_many:
if field.many_to_many:
return compare.M2MFieldComparison
return compare.ForeignObjectComparison
if isinstance(field, RichTextField):
return compare.RichTextFieldComparison
if isinstance(field, (CharField, TextField)):
return compare.TextFieldComparison
except FieldDoesNotExist:
pass