kopia lustrzana https://github.com/wagtail/wagtail
Restore ability to use non-model fields with FieldPanel
This feature is documented in http://docs.wagtail.io/en/v1.11.1/advanced_topics/customisation/page_editing_interface.html but was broken by the EditHandler refactor #3810 - see https://github.com/wagtail/wagtail/pull/4053#issuecomment-380594092pull/4469/merge
rodzic
06227a11ea
commit
63fb483efb
|
@ -7,7 +7,7 @@ from django.forms.formsets import DELETION_FIELD_NAME, ORDERING_FIELD_NAME
|
|||
from django.forms.models import fields_for_model
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.encoding import force_text
|
||||
from django.utils.functional import curry
|
||||
from django.utils.functional import cached_property, curry
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import ugettext_lazy
|
||||
from taggit.managers import TaggableManager
|
||||
|
@ -511,8 +511,14 @@ class FieldPanel(EditHandler):
|
|||
return [curry(comparator_class, self.db_field)]
|
||||
return []
|
||||
|
||||
def on_model_bound(self):
|
||||
self.db_field = self.model._meta.get_field(self.field_name)
|
||||
@cached_property
|
||||
def db_field(self):
|
||||
try:
|
||||
model = self.model
|
||||
except AttributeError:
|
||||
raise ImproperlyConfigured("%r must be bound to a model before calling db_field" % self)
|
||||
|
||||
return model._meta.get_field(self.field_name)
|
||||
|
||||
def on_instance_bound(self):
|
||||
self.bound_field = self.form[self.field_name]
|
||||
|
|
|
@ -376,9 +376,14 @@ class TestFieldPanel(TestCase):
|
|||
self.end_date_panel = (FieldPanel('date_to', classname='full-width')
|
||||
.bind_to_model(EventPage))
|
||||
|
||||
def test_invalid_field(self):
|
||||
def test_non_model_field(self):
|
||||
# defining a FieldPanel for a field which isn't part of a model is OK,
|
||||
# because it might be defined on the form instead
|
||||
field_panel = FieldPanel('barbecue').bind_to_model(Page)
|
||||
|
||||
# however, accessing db_field will fail
|
||||
with self.assertRaises(FieldDoesNotExist):
|
||||
FieldPanel('barbecue').bind_to_model(Page)
|
||||
field_panel.db_field
|
||||
|
||||
def test_render_as_object(self):
|
||||
form = self.EventPageForm(
|
||||
|
|
|
@ -682,6 +682,15 @@ class TestPageCreation(TestCase, WagtailTestUtils):
|
|||
self.assertContains(response, '<a href="#tab-promote" class="">Promote</a>')
|
||||
self.assertContains(response, '<a href="#tab-dinosaurs" class="">Dinosaurs</a>')
|
||||
|
||||
def test_create_page_with_non_model_field(self):
|
||||
"""
|
||||
Test that additional fields defined on the form rather than the model are accepted and rendered
|
||||
"""
|
||||
response = self.client.get(reverse('wagtailadmin_pages:add', args=('tests', 'formclassadditionalfieldpage', self.root_page.id)))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'wagtailadmin/pages/create.html')
|
||||
self.assertContains(response, "Enter SMS authentication code")
|
||||
|
||||
def test_create_simplepage_bad_permissions(self):
|
||||
# Remove privileges from user
|
||||
self.user.is_superuser = False
|
||||
|
|
|
@ -12,3 +12,18 @@ class ValidatedPageForm(WagtailAdminPageForm):
|
|||
if value != 'bar':
|
||||
raise forms.ValidationError('Field foo must be bar')
|
||||
return value
|
||||
|
||||
|
||||
class FormClassAdditionalFieldPageForm(WagtailAdminPageForm):
|
||||
code = forms.CharField(
|
||||
help_text='Enter SMS authentication code', max_length=5)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(FormClassAdditionalFieldPageForm, self).clean()
|
||||
|
||||
# validate the user's code with our code check
|
||||
code = cleaned_data['code']
|
||||
if not code:
|
||||
raise forms.ValidationError('Code is not valid')
|
||||
|
||||
return cleaned_data
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 2.0.4 on 2018-04-12 15:10
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import wagtail.core.fields
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('wagtailcore', '0040_page_draft_title'),
|
||||
('tests', '0029_auto_20180215_1950'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='FormClassAdditionalFieldPage',
|
||||
fields=[
|
||||
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
|
||||
('location', models.CharField(max_length=255)),
|
||||
('body', wagtail.core.fields.RichTextField(blank=True)),
|
||||
],
|
||||
options={
|
||||
'abstract': False,
|
||||
},
|
||||
bases=('wagtailcore.page',),
|
||||
),
|
||||
]
|
|
@ -39,7 +39,7 @@ from wagtail.search import index
|
|||
from wagtail.snippets.edit_handlers import SnippetChooserPanel
|
||||
from wagtail.snippets.models import register_snippet
|
||||
|
||||
from .forms import ValidatedPageForm
|
||||
from .forms import FormClassAdditionalFieldPageForm, ValidatedPageForm
|
||||
from .views import CustomSubmissionsListView
|
||||
|
||||
EVENT_AUDIENCE_CHOICES = (
|
||||
|
@ -314,6 +314,22 @@ class HeadCountRelatedModelUsingPK(models.Model):
|
|||
panels = [FieldPanel('head_count')]
|
||||
|
||||
|
||||
# Override the standard WagtailAdminPageForm to add field that is not in model
|
||||
# so that we can test additional potential issues like comparing versions
|
||||
class FormClassAdditionalFieldPage(Page):
|
||||
location = models.CharField(max_length=255)
|
||||
body = RichTextField(blank=True)
|
||||
|
||||
content_panels = [
|
||||
FieldPanel('title', classname="full title"),
|
||||
FieldPanel('location'),
|
||||
FieldPanel('body'),
|
||||
FieldPanel('code'), # not in model, see set base_form_class
|
||||
]
|
||||
|
||||
base_form_class = FormClassAdditionalFieldPageForm
|
||||
|
||||
|
||||
# Just to be able to test multi table inheritance
|
||||
class SingleEventPage(EventPage):
|
||||
excerpt = models.TextField(
|
||||
|
|
Ładowanie…
Reference in New Issue