kopia lustrzana https://github.com/wagtail/wagtail
rodzic
b7ab0496f1
commit
5a1ba5abe2
|
@ -25,6 +25,7 @@ Changelog
|
|||
* Docs: Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
|
||||
* Docs: Document Wagtail's bug bounty policy (Jake Howard)
|
||||
* Docs: Fix incorrect Sphinx-style code references to use MyST style (Byron Peebles)
|
||||
* Docs: Document the fact that `Orderable` is not required for inline panels (Bojan Mihelac)
|
||||
* Maintenance: Use `DjangoJSONEncoder` instead of custom `LazyStringEncoder` to serialize Draftail config (Sage Abdullah)
|
||||
* Maintenance: Refactor image chooser pagination to check `WAGTAILIMAGES_CHOOSER_PAGE_SIZE` at runtime (Matt Westcott)
|
||||
* Maintenance: Exclude the `client/scss` directory in Tailwind content config to speed up CSS compilation (Sage Abdullah)
|
||||
|
|
|
@ -43,6 +43,7 @@ depth: 1
|
|||
* Document `restriction_type` field on PageViewRestriction (Shlomo Markowitz)
|
||||
* Document Wagtail's bug bounty policy (Jake Howard)
|
||||
* Fix incorrect Sphinx-style code references to use MyST style (Byron Peebles)
|
||||
* Document the fact that `Orderable` is not required for inline panels (Bojan Mihelac)
|
||||
|
||||
|
||||
### Maintenance
|
||||
|
|
|
@ -333,10 +333,7 @@ class BlogPage(Page):
|
|||
|
||||
Wagtail allows the nesting of other models within a page. This is useful for creating repeated fields, such as related links or items to display in a carousel. Inline model content is also versioned with the rest of the page.
|
||||
|
||||
Each inline model requires the following:
|
||||
|
||||
- It must inherit from {class}`wagtail.models.Orderable`
|
||||
- It must have a `ParentalKey` to the parent model
|
||||
An inline model must have a `ParentalKey` pointing to the parent model. It can also inherit from {class}`wagtail.models.Orderable` to allow reordering of items in the admin interface.
|
||||
|
||||
````{note}
|
||||
The model inlining feature is provided by [django-modelcluster](https://github.com/wagtail/django-modelcluster) and the `ParentalKey` field type must be imported from there:
|
||||
|
|
|
@ -1563,6 +1563,10 @@ class TestInlinePanelWithTags(WagtailTestUtils, TestCase):
|
|||
"comments-INITIAL_FORMS": 0,
|
||||
"comments-MIN_NUM_FORMS": 0,
|
||||
"comments-MAX_NUM_FORMS": 1000,
|
||||
"social_links-TOTAL_FORMS": 0,
|
||||
"social_links-INITIAL_FORMS": 0,
|
||||
"social_links-MIN_NUM_FORMS": 0,
|
||||
"social_links-MAX_NUM_FORMS": 1000,
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
|
@ -1578,6 +1582,49 @@ class TestInlinePanelWithTags(WagtailTestUtils, TestCase):
|
|||
self.assertEqual(new_page.addresses.first().tags.count(), 2)
|
||||
|
||||
|
||||
class TestNonOrderableInlinePanel(WagtailTestUtils, TestCase):
|
||||
# https://github.com/wagtail/wagtail/issues/11887
|
||||
|
||||
def setUp(self):
|
||||
self.root_page = Page.objects.get(id=2)
|
||||
self.user = self.login()
|
||||
|
||||
def test_create(self):
|
||||
post_data = {
|
||||
"title": "Mr Benn",
|
||||
"slug": "mr-benn",
|
||||
"first_name": "William",
|
||||
"last_name": "Benn",
|
||||
"addresses-TOTAL_FORMS": 0,
|
||||
"addresses-INITIAL_FORMS": 0,
|
||||
"addresses-MIN_NUM_FORMS": 0,
|
||||
"addresses-MAX_NUM_FORMS": 1000,
|
||||
"action-publish": "Publish",
|
||||
"comments-TOTAL_FORMS": 0,
|
||||
"comments-INITIAL_FORMS": 0,
|
||||
"comments-MIN_NUM_FORMS": 0,
|
||||
"comments-MAX_NUM_FORMS": 1000,
|
||||
"social_links-TOTAL_FORMS": 1,
|
||||
"social_links-INITIAL_FORMS": 0,
|
||||
"social_links-MIN_NUM_FORMS": 0,
|
||||
"social_links-MAX_NUM_FORMS": 1000,
|
||||
"social_links-0-url": "https://twitter.com/mrbenn",
|
||||
"social_links-0-kind": "twitter",
|
||||
}
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"wagtailadmin_pages:add",
|
||||
args=("tests", "personpage", self.root_page.id),
|
||||
),
|
||||
post_data,
|
||||
)
|
||||
self.assertRedirects(
|
||||
response, reverse("wagtailadmin_explore", args=(self.root_page.id,))
|
||||
)
|
||||
new_page = PersonPage.objects.get(slug="mr-benn")
|
||||
self.assertEqual(new_page.social_links.count(), 1)
|
||||
|
||||
|
||||
class TestInlinePanelNonFieldErrors(WagtailTestUtils, TestCase):
|
||||
"""
|
||||
Test that non field errors will render for InlinePanels
|
||||
|
|
|
@ -52,6 +52,7 @@ from wagtail.test.testapp.models import (
|
|||
FormPageWithRedirect,
|
||||
GalleryPage,
|
||||
PageChooserModel,
|
||||
PersonPage,
|
||||
RestaurantPage,
|
||||
RestaurantTag,
|
||||
SimplePage,
|
||||
|
@ -1522,6 +1523,42 @@ class TestInlinePanel(WagtailTestUtils, TestCase):
|
|||
)
|
||||
|
||||
|
||||
class TestNonOrderableInlinePanel(WagtailTestUtils, TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
def setUp(self):
|
||||
self.request = get_dummy_request()
|
||||
user = AnonymousUser() # technically, Anonymous users cannot access the admin
|
||||
self.request.user = user
|
||||
|
||||
def test_render(self):
|
||||
"""
|
||||
Check that the inline panel renders the panels set on the model
|
||||
when no 'panels' parameter is passed in the InlinePanel definition
|
||||
"""
|
||||
social_link_object_list = ObjectList(
|
||||
[
|
||||
InlinePanel(
|
||||
"social_links",
|
||||
label="Social Links",
|
||||
)
|
||||
]
|
||||
).bind_to_model(PersonPage)
|
||||
PersonPageForm = social_link_object_list.get_form_class()
|
||||
|
||||
person_page = PersonPage()
|
||||
form = PersonPageForm(instance=person_page)
|
||||
panel = social_link_object_list.get_bound_panel(
|
||||
instance=person_page, form=form, request=self.request
|
||||
)
|
||||
result = panel.render_html()
|
||||
# rendered panel must not contain hidden fields for ORDER
|
||||
self.assertNotInHTML(
|
||||
'id="id_social_links-__prefix__-ORDER"',
|
||||
result,
|
||||
)
|
||||
|
||||
|
||||
class TestInlinePanelGetComparison(TestCase):
|
||||
fixtures = ["test.json"]
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
# Generated by Django 4.2.13 on 2024-06-12 12:06
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import modelcluster.fields
|
||||
import wagtail.search.index
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("tests", "0037_testpermissionedgenericsetting_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="SocialLink",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("url", models.URLField()),
|
||||
(
|
||||
"kind",
|
||||
models.CharField(
|
||||
choices=[("twitter", "Twitter"), ("facebook", "Facebook")],
|
||||
max_length=30,
|
||||
),
|
||||
),
|
||||
(
|
||||
"person",
|
||||
modelcluster.fields.ParentalKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="social_links",
|
||||
to="tests.personpage",
|
||||
verbose_name="Person",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Social link",
|
||||
"verbose_name_plural": "Social links",
|
||||
},
|
||||
bases=(wagtail.search.index.Indexed, models.Model),
|
||||
),
|
||||
]
|
|
@ -2097,6 +2097,7 @@ class PersonPage(Page):
|
|||
"Person",
|
||||
),
|
||||
InlinePanel("addresses", label="Address"),
|
||||
InlinePanel("social_links", label="Social links"),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
|
@ -2133,6 +2134,29 @@ class AddressTag(TaggedItemBase):
|
|||
)
|
||||
|
||||
|
||||
class SocialLink(index.Indexed, ClusterableModel):
|
||||
url = models.URLField()
|
||||
kind = models.CharField(
|
||||
max_length=30,
|
||||
choices=[
|
||||
("twitter", "Twitter"),
|
||||
("facebook", "Facebook"),
|
||||
],
|
||||
)
|
||||
person = ParentalKey(
|
||||
to="tests.PersonPage", related_name="social_links", verbose_name="Person"
|
||||
)
|
||||
|
||||
panels = [
|
||||
FieldPanel("url"),
|
||||
FieldPanel("kind"),
|
||||
]
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Social link"
|
||||
verbose_name_plural = "Social links"
|
||||
|
||||
|
||||
class RestaurantPage(Page):
|
||||
tags = ClusterTaggableManager(through="tests.TaggedRestaurant", blank=True)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue