kopia lustrzana https://github.com/wagtail/wagtail
Make document upload forms use the correct widget for custom tag models
rodzic
46efee9eeb
commit
f57fc32ed0
wagtail
documents
test/testapp
|
@ -3,12 +3,12 @@ from django.conf import settings
|
|||
from django.forms.models import modelform_factory
|
||||
from django.utils.translation import gettext_lazy 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.documents.models import Document
|
||||
from wagtail.documents.permissions import (
|
||||
permission_policy as documents_permission_policy,
|
||||
|
@ -34,7 +34,7 @@ class BaseDocumentForm(BaseCollectionMemberForm):
|
|||
permission_policy = documents_permission_policy
|
||||
|
||||
class Meta:
|
||||
widgets = {"tags": widgets.AdminTagWidget, "file": forms.FileInput()}
|
||||
widgets = {"tags": AdminTagWidget, "file": forms.FileInput()}
|
||||
|
||||
|
||||
def get_document_base_form():
|
||||
|
@ -57,10 +57,23 @@ def get_document_form(model):
|
|||
# and when only one collection exists, it will get hidden anyway.
|
||||
fields = list(fields) + ["collection"]
|
||||
|
||||
BaseForm = get_document_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 document model.
|
||||
# (If the widget has been overridden via WAGTAILDOCS_DOCUMENT_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_document_base_form(),
|
||||
form=BaseForm,
|
||||
fields=fields,
|
||||
widgets=widgets,
|
||||
formfield_callback=formfield_for_dbfield,
|
||||
)
|
||||
|
||||
|
@ -73,10 +86,23 @@ def get_document_multi_form(model):
|
|||
if "collection" not in fields:
|
||||
fields.append("collection")
|
||||
|
||||
BaseForm = get_document_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 document model.
|
||||
# (If the widget has been overridden via WAGTAILDOCS_DOCUMENT_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_document_base_form(),
|
||||
form=BaseForm,
|
||||
fields=fields,
|
||||
widgets=widgets,
|
||||
formfield_callback=formfield_for_dbfield,
|
||||
)
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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
|
||||
|
@ -11,6 +12,7 @@ from wagtail.documents.forms import (
|
|||
get_document_multi_form,
|
||||
)
|
||||
from wagtail.test.testapp.media_forms import AlternateDocumentForm, OverriddenWidget
|
||||
from wagtail.test.testapp.models import CustomRestaurantDocument, RestaurantTag
|
||||
|
||||
|
||||
class TestDocumentFormOverride(TestCase):
|
||||
|
@ -26,8 +28,15 @@ class TestDocumentFormOverride(TestCase):
|
|||
form_cls = get_document_form(models.Document)
|
||||
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)
|
||||
|
||||
def test_tags_widget_with_custom_tag_model(self):
|
||||
form_cls = get_document_form(CustomRestaurantDocument)
|
||||
form = form_cls()
|
||||
self.assertIsInstance(form.fields["tags"].widget, widgets.AdminTagWidget)
|
||||
self.assertEqual(form.fields["tags"].widget.tag_model, RestaurantTag)
|
||||
|
||||
@override_settings(
|
||||
WAGTAILDOCS_DOCUMENT_FORM_BASE="wagtail.test.testapp.media_forms.AlternateDocumentForm"
|
||||
)
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
# Generated by Django 3.2.11 on 2022-01-27 15:00
|
||||
|
||||
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.search.index
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("wagtailcore", "0066_collection_management_permissions"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("tests", "0063_jsonblockcountsstreammodel_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CustomRestaurantDocument",
|
||||
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.FileField(upload_to="documents", verbose_name="file")),
|
||||
(
|
||||
"created_at",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="created at"),
|
||||
),
|
||||
("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={
|
||||
"verbose_name": "document",
|
||||
"verbose_name_plural": "documents",
|
||||
"abstract": False,
|
||||
},
|
||||
bases=(wagtail.search.index.Indexed, models.Model),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="TaggedRestaurantDocument",
|
||||
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.customrestaurantdocument",
|
||||
),
|
||||
),
|
||||
(
|
||||
"tag",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="tagged_documents",
|
||||
to="tests.restauranttag",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="customrestaurantdocument",
|
||||
name="tags",
|
||||
field=taggit.managers.TaggableManager(
|
||||
blank=True,
|
||||
help_text=None,
|
||||
through="tests.TaggedRestaurantDocument",
|
||||
to="tests.RestaurantTag",
|
||||
verbose_name="tags",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="customrestaurantdocument",
|
||||
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",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1712,3 +1712,25 @@ class DeadlyStreamPage(Page):
|
|||
# (so that it's possible to use them in foreign key definitions, for example)
|
||||
ReimportedImageModel = get_image_model()
|
||||
ReimportedDocumentModel = get_document_model()
|
||||
|
||||
|
||||
# Custom document model with a custom tag field
|
||||
class TaggedRestaurantDocument(ItemBase):
|
||||
tag = models.ForeignKey(
|
||||
RestaurantTag, related_name="tagged_documents", on_delete=models.CASCADE
|
||||
)
|
||||
content_object = models.ForeignKey(
|
||||
to="tests.CustomRestaurantDocument",
|
||||
on_delete=models.CASCADE,
|
||||
related_name="tagged_items",
|
||||
)
|
||||
|
||||
|
||||
class CustomRestaurantDocument(AbstractDocument):
|
||||
tags = TaggableManager(
|
||||
help_text=None,
|
||||
blank=True,
|
||||
verbose_name="tags",
|
||||
through=TaggedRestaurantDocument,
|
||||
)
|
||||
admin_form_fields = Document.admin_form_fields
|
||||
|
|
Ładowanie…
Reference in New Issue