Make image upload forms use the correct widget for custom tag models

pull/8592/head
Matt Westcott 2022-01-27 16:33:17 +00:00 zatwierdzone przez LB (Ben Johnston)
rodzic f57fc32ed0
commit 246a270f10
4 zmienionych plików z 186 dodań i 3 usunięć

Wyświetl plik

@ -4,12 +4,12 @@ from django.forms.models import modelform_factory
from django.utils.text import capfirst
from django.utils.translation import gettext as _
from wagtail.admin import widgets
from wagtail.admin.forms.collections import (
BaseCollectionMemberForm,
CollectionChoiceField,
collection_member_permission_formset_factory,
)
from wagtail.admin.widgets import AdminTagWidget
from wagtail.images.fields import WagtailImageField
from wagtail.images.formats import get_image_formats
from wagtail.images.models import Image
@ -42,7 +42,7 @@ class BaseImageForm(BaseCollectionMemberForm):
# so that when editing, we don't get the 'currently: ...' banner which is
# a bit pointless here
widgets = {
"tags": widgets.AdminTagWidget,
"tags": AdminTagWidget,
"file": forms.FileInput(),
"focal_point_x": forms.HiddenInput(attrs={"class": "focal_point_x"}),
"focal_point_y": forms.HiddenInput(attrs={"class": "focal_point_y"}),
@ -75,10 +75,23 @@ def get_image_form(model):
# and when only one collection exists, it will get hidden anyway.
fields = list(fields) + ["collection"]
BaseForm = get_image_base_form()
# If the base form specifies the 'tags' widget as a plain unconfigured AdminTagWidget,
# substitute one that correctly passes the tag model used on the image model.
# (If the widget has been overridden via WAGTAILIMAGES_IMAGE_FORM_BASE, leave it
# alone and trust that they know what they're doing)
widgets = None
if BaseForm._meta.widgets.get("tags") == AdminTagWidget:
tag_model = model._meta.get_field("tags").related_model
widgets = BaseForm._meta.widgets.copy()
widgets["tags"] = AdminTagWidget(tag_model=tag_model)
return modelform_factory(
model,
form=get_image_base_form(),
form=BaseForm,
fields=fields,
widgets=widgets,
formfield_callback=formfield_for_dbfield,
)

Wyświetl plik

@ -1,11 +1,13 @@
from django import forms
from django.test import TestCase, override_settings
from taggit import models as taggit_models
from wagtail.admin import widgets
from wagtail.admin.widgets import AdminDateTimeInput
from wagtail.images import models
from wagtail.images.forms import BaseImageForm, get_image_base_form, get_image_form
from wagtail.test.testapp.media_forms import AlternateImageForm, OverriddenWidget
from wagtail.test.testapp.models import CustomRestaurantImage, RestaurantTag
class TestImageFormOverride(TestCase):
@ -21,9 +23,16 @@ class TestImageFormOverride(TestCase):
form_cls = get_image_form(models.Image)
form = form_cls()
self.assertIsInstance(form.fields["tags"].widget, widgets.AdminTagWidget)
self.assertEqual(form.fields["tags"].widget.tag_model, taggit_models.Tag)
self.assertIsInstance(form.fields["file"].widget, forms.FileInput)
self.assertIsInstance(form.fields["focal_point_x"].widget, forms.HiddenInput)
def test_tags_widget_with_custom_tag_model(self):
form_cls = get_image_form(CustomRestaurantImage)
form = form_cls()
self.assertIsInstance(form.fields["tags"].widget, widgets.AdminTagWidget)
self.assertEqual(form.fields["tags"].widget.tag_model, RestaurantTag)
@override_settings(
WAGTAILIMAGES_IMAGE_FORM_BASE="wagtail.test.testapp.media_forms.AlternateImageForm"
)

Wyświetl plik

@ -0,0 +1,142 @@
# Generated by Django 3.2.11 on 2022-01-27 16:23
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import taggit.managers
import wagtail.core.models.collections
import wagtail.images.models
import wagtail.search.index
class Migration(migrations.Migration):
dependencies = [
("wagtailcore", "0066_collection_management_permissions"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("tests", "0064_tagged_restaurant_document"),
]
operations = [
migrations.CreateModel(
name="CustomRestaurantImage",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255, verbose_name="title")),
(
"file",
models.ImageField(
height_field="height",
upload_to=wagtail.images.models.get_upload_to,
verbose_name="file",
width_field="width",
),
),
("width", models.IntegerField(editable=False, verbose_name="width")),
("height", models.IntegerField(editable=False, verbose_name="height")),
(
"created_at",
models.DateTimeField(
auto_now_add=True, db_index=True, verbose_name="created at"
),
),
("focal_point_x", models.PositiveIntegerField(blank=True, null=True)),
("focal_point_y", models.PositiveIntegerField(blank=True, null=True)),
(
"focal_point_width",
models.PositiveIntegerField(blank=True, null=True),
),
(
"focal_point_height",
models.PositiveIntegerField(blank=True, null=True),
),
("file_size", models.PositiveIntegerField(editable=False, null=True)),
(
"file_hash",
models.CharField(blank=True, editable=False, max_length=40),
),
(
"collection",
models.ForeignKey(
default=wagtail.core.models.collections.get_root_collection_id,
on_delete=django.db.models.deletion.CASCADE,
related_name="+",
to="wagtailcore.collection",
verbose_name="collection",
),
),
],
options={
"abstract": False,
},
bases=(
wagtail.images.models.ImageFileMixin,
wagtail.search.index.Indexed,
models.Model,
),
),
migrations.CreateModel(
name="TaggedRestaurantImage",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"content_object",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="tagged_items",
to="tests.customrestaurantimage",
),
),
(
"tag",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="tagged_images",
to="tests.restauranttag",
),
),
],
options={
"abstract": False,
},
),
migrations.AddField(
model_name="customrestaurantimage",
name="tags",
field=taggit.managers.TaggableManager(
blank=True,
help_text=None,
through="tests.TaggedRestaurantImage",
to="tests.RestaurantTag",
verbose_name="tags",
),
),
migrations.AddField(
model_name="customrestaurantimage",
name="uploaded_by_user",
field=models.ForeignKey(
blank=True,
editable=False,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
verbose_name="uploaded by user",
),
),
]

Wyświetl plik

@ -1734,3 +1734,22 @@ class CustomRestaurantDocument(AbstractDocument):
through=TaggedRestaurantDocument,
)
admin_form_fields = Document.admin_form_fields
# Custom image model with a custom tag field
class TaggedRestaurantImage(ItemBase):
tag = models.ForeignKey(
RestaurantTag, related_name="tagged_images", on_delete=models.CASCADE
)
content_object = models.ForeignKey(
to="tests.CustomRestaurantImage",
on_delete=models.CASCADE,
related_name="tagged_items",
)
class CustomRestaurantImage(AbstractImage):
tags = TaggableManager(
help_text=None, blank=True, verbose_name="tags", through=TaggedRestaurantImage
)
admin_form_fields = Image.admin_form_fields