mirror of
https://github.com/wagtail/wagtail.git
synced 2024-12-01 11:41:20 +01:00
Move page validation to WagtailAdminPageForm class
Page validation is now done through the WagtailAdminPageForm class, instead of through a separate function.
This commit is contained in:
parent
8bb6982175
commit
83d8c1a50e
@ -1,120 +1,48 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import copy
|
||||
|
||||
from modelcluster.forms import ClusterForm, ClusterFormMetaclass
|
||||
|
||||
import django
|
||||
from django.db import models
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.six import text_type
|
||||
from django import forms
|
||||
from django.forms.models import fields_for_model
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.forms.models import fields_for_model
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils.lru_cache import lru_cache
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.six import text_type
|
||||
from django.utils.translation import ugettext_lazy
|
||||
|
||||
from taggit.managers import TaggableManager
|
||||
|
||||
from wagtail.wagtailadmin import widgets
|
||||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.wagtailcore.utils import camelcase_to_underscore, resolve_model_string
|
||||
from wagtail.wagtailcore.utils import (
|
||||
camelcase_to_underscore, resolve_model_string)
|
||||
|
||||
|
||||
# Form field properties to override whenever we encounter a model field
|
||||
# that matches one of these types - including subclasses
|
||||
FORM_FIELD_OVERRIDES = {
|
||||
models.DateField: {'widget': widgets.AdminDateInput},
|
||||
models.TimeField: {'widget': widgets.AdminTimeInput},
|
||||
models.DateTimeField: {'widget': widgets.AdminDateTimeInput},
|
||||
TaggableManager: {'widget': widgets.AdminTagWidget},
|
||||
}
|
||||
|
||||
# Form field properties to override whenever we encounter a model field
|
||||
# that matches one of these types exactly, ignoring subclasses.
|
||||
# (This allows us to override the widget for models.TextField, but leave
|
||||
# the RichTextField widget alone)
|
||||
DIRECT_FORM_FIELD_OVERRIDES = {
|
||||
models.TextField: {'widget': widgets.AdminAutoHeightTextInput},
|
||||
}
|
||||
|
||||
|
||||
# Callback to allow us to override the default form fields provided for each model field.
|
||||
def formfield_for_dbfield(db_field, **kwargs):
|
||||
# adapted from django/contrib/admin/options.py
|
||||
|
||||
overrides = None
|
||||
|
||||
# If we've got overrides for the formfield defined, use 'em. **kwargs
|
||||
# passed to formfield_for_dbfield override the defaults.
|
||||
if db_field.__class__ in DIRECT_FORM_FIELD_OVERRIDES:
|
||||
overrides = DIRECT_FORM_FIELD_OVERRIDES[db_field.__class__]
|
||||
else:
|
||||
for klass in db_field.__class__.mro():
|
||||
if klass in FORM_FIELD_OVERRIDES:
|
||||
overrides = FORM_FIELD_OVERRIDES[klass]
|
||||
break
|
||||
|
||||
if overrides:
|
||||
kwargs = dict(copy.deepcopy(overrides), **kwargs)
|
||||
|
||||
return db_field.formfield(**kwargs)
|
||||
# DIRECT_FORM_FIELD_OVERRIDES, FORM_FIELD_OVERRIDES are imported for backwards
|
||||
# compatibility, as people are likely importing them from here and then
|
||||
# appending their own overrides
|
||||
from .forms import ( # NOQA
|
||||
DIRECT_FORM_FIELD_OVERRIDES, FORM_FIELD_OVERRIDES, WagtailAdminModelForm,
|
||||
WagtailAdminPageForm, formfield_for_dbfield)
|
||||
|
||||
|
||||
def widget_with_script(widget, script):
|
||||
return mark_safe('{0}<script>{1}</script>'.format(widget, script))
|
||||
|
||||
|
||||
class WagtailAdminModelFormMetaclass(ClusterFormMetaclass):
|
||||
# Override the behaviour of the regular ModelForm metaclass -
|
||||
# which handles the translation of model fields to form fields -
|
||||
# to use our own formfield_for_dbfield function to do that translation.
|
||||
# This is done by sneaking a formfield_callback property into the class
|
||||
# being defined (unless the class already provides a formfield_callback
|
||||
# of its own).
|
||||
|
||||
# while we're at it, we'll also set extra_form_count to 0, as we're creating
|
||||
# extra forms in JS
|
||||
extra_form_count = 0
|
||||
|
||||
def __new__(cls, name, bases, attrs):
|
||||
if 'formfield_callback' not in attrs or attrs['formfield_callback'] is None:
|
||||
attrs['formfield_callback'] = formfield_for_dbfield
|
||||
|
||||
new_class = super(WagtailAdminModelFormMetaclass, cls).__new__(cls, name, bases, attrs)
|
||||
return new_class
|
||||
|
||||
WagtailAdminModelForm = WagtailAdminModelFormMetaclass(str('WagtailAdminModelForm'), (ClusterForm,), {})
|
||||
|
||||
# Now, any model forms built off WagtailAdminModelForm instead of ModelForm should pick up
|
||||
# the nice form fields defined in FORM_FIELD_OVERRIDES.
|
||||
|
||||
|
||||
def get_form_for_model(
|
||||
model, form_class=WagtailAdminModelForm,
|
||||
fields=None, exclude=None, formsets=None, exclude_formsets=None, widgets=None
|
||||
):
|
||||
|
||||
# django's modelform_factory with a bit of custom behaviour
|
||||
# (dealing with Treebeard's tree-related fields that really should have
|
||||
# been editable=False)
|
||||
attrs = {'model': model}
|
||||
|
||||
if fields is not None:
|
||||
attrs['fields'] = fields
|
||||
|
||||
if exclude is not None:
|
||||
attrs['exclude'] = exclude
|
||||
if issubclass(model, Page):
|
||||
attrs['exclude'] = attrs.get('exclude', []) + ['content_type', 'path', 'depth', 'numchild']
|
||||
|
||||
if widgets is not None:
|
||||
attrs['widgets'] = widgets
|
||||
|
||||
if formsets is not None:
|
||||
attrs['formsets'] = formsets
|
||||
|
||||
if exclude_formsets is not None:
|
||||
attrs['exclude_formsets'] = exclude_formsets
|
||||
|
||||
@ -141,8 +69,6 @@ def extract_panel_definitions_from_model_class(model, exclude=None):
|
||||
_exclude = []
|
||||
if exclude:
|
||||
_exclude.extend(exclude)
|
||||
if issubclass(model, Page):
|
||||
_exclude = ['content_type', 'path', 'depth', 'numchild']
|
||||
|
||||
fields = fields_for_model(model, exclude=_exclude, formfield_callback=formfield_for_dbfield)
|
||||
|
||||
@ -781,7 +707,7 @@ Page.settings_panels = [
|
||||
PublishingPanel()
|
||||
]
|
||||
|
||||
Page.base_form_class = WagtailAdminModelForm
|
||||
Page.base_form_class = WagtailAdminPageForm
|
||||
|
||||
|
||||
@classmethod
|
||||
|
@ -1,11 +1,21 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import copy
|
||||
|
||||
import django
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.forms.widgets import TextInput
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.forms import AuthenticationForm, PasswordResetForm
|
||||
from django.core import validators
|
||||
from django.db import models
|
||||
from django.forms.widgets import TextInput
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ungettext, ugettext_lazy
|
||||
from wagtail.wagtailadmin.widgets import AdminPageChooser
|
||||
from django.utils.translation import ugettext_lazy, ungettext
|
||||
from modelcluster.forms import ClusterForm, ClusterFormMetaclass
|
||||
from taggit.managers import TaggableManager
|
||||
|
||||
from wagtail.wagtailadmin import widgets
|
||||
from wagtail.wagtailcore.models import Page
|
||||
|
||||
|
||||
@ -120,7 +130,7 @@ class CopyForm(forms.Form):
|
||||
self.fields['new_parent_page'] = forms.ModelChoiceField(
|
||||
initial=self.page.get_parent(),
|
||||
queryset=Page.objects.all(),
|
||||
widget=AdminPageChooser(can_choose_root=True),
|
||||
widget=widgets.AdminPageChooser(can_choose_root=True),
|
||||
label=_("New parent page"),
|
||||
help_text=_("This copy will be a child of this given parent page.")
|
||||
)
|
||||
@ -188,3 +198,116 @@ class PageViewRestrictionForm(forms.Form):
|
||||
del cleaned_data['password']
|
||||
|
||||
return cleaned_data
|
||||
|
||||
|
||||
# Form field properties to override whenever we encounter a model field
|
||||
# that matches one of these types - including subclasses
|
||||
FORM_FIELD_OVERRIDES = {
|
||||
models.DateField: {'widget': widgets.AdminDateInput},
|
||||
models.TimeField: {'widget': widgets.AdminTimeInput},
|
||||
models.DateTimeField: {'widget': widgets.AdminDateTimeInput},
|
||||
TaggableManager: {'widget': widgets.AdminTagWidget},
|
||||
}
|
||||
|
||||
# Form field properties to override whenever we encounter a model field
|
||||
# that matches one of these types exactly, ignoring subclasses.
|
||||
# (This allows us to override the widget for models.TextField, but leave
|
||||
# the RichTextField widget alone)
|
||||
DIRECT_FORM_FIELD_OVERRIDES = {
|
||||
models.TextField: {'widget': widgets.AdminAutoHeightTextInput},
|
||||
}
|
||||
|
||||
|
||||
# Callback to allow us to override the default form fields provided for each model field.
|
||||
def formfield_for_dbfield(db_field, **kwargs):
|
||||
# adapted from django/contrib/admin/options.py
|
||||
|
||||
overrides = None
|
||||
|
||||
# If we've got overrides for the formfield defined, use 'em. **kwargs
|
||||
# passed to formfield_for_dbfield override the defaults.
|
||||
if db_field.__class__ in DIRECT_FORM_FIELD_OVERRIDES:
|
||||
overrides = DIRECT_FORM_FIELD_OVERRIDES[db_field.__class__]
|
||||
else:
|
||||
for klass in db_field.__class__.mro():
|
||||
if klass in FORM_FIELD_OVERRIDES:
|
||||
overrides = FORM_FIELD_OVERRIDES[klass]
|
||||
break
|
||||
|
||||
if overrides:
|
||||
kwargs = dict(copy.deepcopy(overrides), **kwargs)
|
||||
|
||||
return db_field.formfield(**kwargs)
|
||||
|
||||
|
||||
class WagtailAdminModelFormMetaclass(ClusterFormMetaclass):
|
||||
# Override the behaviour of the regular ModelForm metaclass -
|
||||
# which handles the translation of model fields to form fields -
|
||||
# to use our own formfield_for_dbfield function to do that translation.
|
||||
# This is done by sneaking a formfield_callback property into the class
|
||||
# being defined (unless the class already provides a formfield_callback
|
||||
# of its own).
|
||||
|
||||
# while we're at it, we'll also set extra_form_count to 0, as we're creating
|
||||
# extra forms in JS
|
||||
extra_form_count = 0
|
||||
|
||||
def __new__(cls, name, bases, attrs):
|
||||
if 'formfield_callback' not in attrs or attrs['formfield_callback'] is None:
|
||||
attrs['formfield_callback'] = formfield_for_dbfield
|
||||
|
||||
new_class = super(WagtailAdminModelFormMetaclass, cls).__new__(cls, name, bases, attrs)
|
||||
return new_class
|
||||
|
||||
WagtailAdminModelForm = WagtailAdminModelFormMetaclass(str('WagtailAdminModelForm'), (ClusterForm,), {})
|
||||
|
||||
# Now, any model forms built off WagtailAdminModelForm instead of ModelForm should pick up
|
||||
# the nice form fields defined in FORM_FIELD_OVERRIDES.
|
||||
|
||||
|
||||
class WagtailAdminPageForm(WagtailAdminModelForm):
|
||||
|
||||
class Meta:
|
||||
# (dealing with Treebeard's tree-related fields that really should have
|
||||
# been editable=False)
|
||||
exclude = ['content_type', 'path', 'depth', 'numchild']
|
||||
|
||||
def __init__(self, data=None, files=None, parent_page=None, *args, **kwargs):
|
||||
super(WagtailAdminPageForm, self).__init__(data, files, *args, **kwargs)
|
||||
self.parent_page = parent_page
|
||||
|
||||
if django.VERSION < (1, 9):
|
||||
def clean_title(self):
|
||||
return self.cleaned_data['title'].strip()
|
||||
|
||||
def clean_seo_title(self):
|
||||
return self.cleaned_data['seo_title'].strip()
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super(WagtailAdminPageForm, self).clean()
|
||||
if 'slug' in self.cleaned_data:
|
||||
# Get siblings for the page
|
||||
siblings = self.parent_page.get_children()
|
||||
if self.instance and self.instance.id:
|
||||
siblings = siblings.exclude(id=self.instance.id)
|
||||
|
||||
# Make sure the slug isn't being used by a sibling
|
||||
if siblings.filter(slug=cleaned_data['slug']).exists():
|
||||
self.add_error('slug', forms.ValidationError(_("This slug is already in use")))
|
||||
|
||||
# Check scheduled publishing fields
|
||||
go_live_at = cleaned_data.get('go_live_at')
|
||||
expire_at = cleaned_data.get('expire_at')
|
||||
|
||||
# Go live must be before expire
|
||||
if go_live_at and expire_at:
|
||||
if go_live_at > expire_at:
|
||||
msg = _('Go live date/time must be before expiry date/time')
|
||||
self.add_error('go_live_at', forms.ValidationError(msg))
|
||||
self.add_error('expire_at', forms.ValidationError(msg))
|
||||
|
||||
# Expire at must be in the future
|
||||
if expire_at and expire_at < timezone.now():
|
||||
self.add_error('expire_at', forms.ValidationError(_('Expiry date/time must be in the future')))
|
||||
|
||||
return cleaned_data
|
||||
|
@ -15,6 +15,7 @@ from wagtail.wagtailadmin.edit_handlers import (
|
||||
InlinePanel,
|
||||
)
|
||||
|
||||
from wagtail.wagtailadmin.forms import WagtailAdminModelForm, WagtailAdminPageForm
|
||||
from wagtail.wagtailadmin.widgets import AdminPageChooser, AdminDateInput, AdminAutoHeightTextInput
|
||||
from wagtail.wagtailimages.edit_handlers import ImageChooserPanel
|
||||
from wagtail.wagtailcore.models import Page, Site
|
||||
@ -27,9 +28,11 @@ from wagtail.tests.utils import WagtailTestUtils
|
||||
|
||||
class TestGetFormForModel(TestCase):
|
||||
def test_get_form_for_model(self):
|
||||
EventPageForm = get_form_for_model(EventPage)
|
||||
EventPageForm = get_form_for_model(EventPage, form_class=WagtailAdminPageForm)
|
||||
form = EventPageForm()
|
||||
|
||||
# form should be a subclass of WagtailAdminModelForm
|
||||
self.assertTrue(issubclass(EventPageForm, WagtailAdminModelForm))
|
||||
# form should contain a title field (from the base Page)
|
||||
self.assertEqual(type(form.fields['title']), forms.CharField)
|
||||
# and 'date_from' from EventPage
|
||||
@ -48,19 +51,21 @@ class TestGetFormForModel(TestCase):
|
||||
# Test that field overrides defined through DIRECT_FORM_FIELD_OVERRIDES
|
||||
# are applied
|
||||
|
||||
SimplePageForm = get_form_for_model(SimplePage)
|
||||
SimplePageForm = get_form_for_model(SimplePage, form_class=WagtailAdminPageForm)
|
||||
simple_form = SimplePageForm()
|
||||
# plain TextFields should use AdminAutoHeightTextInput as the widget
|
||||
self.assertEqual(type(simple_form.fields['content'].widget), AdminAutoHeightTextInput)
|
||||
|
||||
# This override should NOT be applied to subclasses of TextField such as
|
||||
# RichTextField - they should retain their default widgets
|
||||
EventPageForm = get_form_for_model(EventPage)
|
||||
EventPageForm = get_form_for_model(EventPage, form_class=WagtailAdminPageForm)
|
||||
event_form = EventPageForm()
|
||||
self.assertEqual(type(event_form.fields['body'].widget), RichTextArea)
|
||||
|
||||
def test_get_form_for_model_with_specific_fields(self):
|
||||
EventPageForm = get_form_for_model(EventPage, fields=['date_from'], formsets=['speakers'])
|
||||
EventPageForm = get_form_for_model(
|
||||
EventPage, form_class=WagtailAdminPageForm, fields=['date_from'],
|
||||
formsets=['speakers'])
|
||||
form = EventPageForm()
|
||||
|
||||
# form should contain date_from but not title
|
||||
@ -73,7 +78,9 @@ class TestGetFormForModel(TestCase):
|
||||
self.assertNotIn('related_links', form.formsets)
|
||||
|
||||
def test_get_form_for_model_with_excluded_fields(self):
|
||||
EventPageForm = get_form_for_model(EventPage, exclude=['title'], exclude_formsets=['related_links'])
|
||||
EventPageForm = get_form_for_model(
|
||||
EventPage, form_class=WagtailAdminPageForm,
|
||||
exclude=['title'], exclude_formsets=['related_links'])
|
||||
form = EventPageForm()
|
||||
|
||||
# form should contain date_from but not title
|
||||
@ -81,28 +88,41 @@ class TestGetFormForModel(TestCase):
|
||||
self.assertEqual(type(form.fields['date_from'].widget), AdminDateInput)
|
||||
self.assertNotIn('title', form.fields)
|
||||
|
||||
# 'path' should still be excluded even though it isn't explicitly in the exclude list
|
||||
self.assertNotIn('path', form.fields)
|
||||
# 'path' is not excluded any more, as the excluded fields were overridden
|
||||
self.assertIn('path', form.fields)
|
||||
|
||||
# formsets should include speakers but not related_links
|
||||
self.assertIn('speakers', form.formsets)
|
||||
self.assertNotIn('related_links', form.formsets)
|
||||
|
||||
def test_get_form_for_model_with_widget_overides_by_class(self):
|
||||
EventPageForm = get_form_for_model(EventPage, widgets={'date_from': forms.PasswordInput})
|
||||
EventPageForm = get_form_for_model(
|
||||
EventPage, form_class=WagtailAdminPageForm,
|
||||
widgets={'date_from': forms.PasswordInput})
|
||||
form = EventPageForm()
|
||||
|
||||
self.assertEqual(type(form.fields['date_from']), forms.DateField)
|
||||
self.assertEqual(type(form.fields['date_from'].widget), forms.PasswordInput)
|
||||
|
||||
def test_get_form_for_model_with_widget_overides_by_instance(self):
|
||||
EventPageForm = get_form_for_model(EventPage, widgets={'date_from': forms.PasswordInput()})
|
||||
EventPageForm = get_form_for_model(
|
||||
EventPage, form_class=WagtailAdminPageForm,
|
||||
widgets={'date_from': forms.PasswordInput()})
|
||||
form = EventPageForm()
|
||||
|
||||
self.assertEqual(type(form.fields['date_from']), forms.DateField)
|
||||
self.assertEqual(type(form.fields['date_from'].widget), forms.PasswordInput)
|
||||
|
||||
|
||||
class TestPageEditHandlers(TestCase):
|
||||
def test_get_edit_handler(self):
|
||||
EditHandler = EventPage.get_edit_handler()
|
||||
EventPageForm = EditHandler.get_form_class(EventPage)
|
||||
|
||||
# The generated form should inherit from WagtailAdminPageForm
|
||||
self.assertTrue(issubclass(EventPageForm, WagtailAdminPageForm))
|
||||
|
||||
|
||||
class TestExtractPanelDefinitionsFromModelClass(TestCase):
|
||||
def test_can_extract_panel_property(self):
|
||||
# A class with a 'panels' property defined should return that list
|
||||
@ -130,12 +150,6 @@ class TestExtractPanelDefinitionsFromModelClass(TestCase):
|
||||
for panel in panels
|
||||
]))
|
||||
|
||||
# treebeard fields should be excluded
|
||||
self.assertFalse(any([
|
||||
panel.field_name == 'path'
|
||||
for panel in panels
|
||||
]))
|
||||
|
||||
|
||||
class TestTabbedInterface(TestCase):
|
||||
def setUp(self):
|
||||
@ -261,7 +275,8 @@ class TestObjectList(TestCase):
|
||||
|
||||
class TestFieldPanel(TestCase):
|
||||
def setUp(self):
|
||||
self.EventPageForm = get_form_for_model(EventPage, formsets=[])
|
||||
self.EventPageForm = get_form_for_model(
|
||||
EventPage, form_class=WagtailAdminPageForm, formsets=[])
|
||||
self.event = EventPage(title='Abergavenny sheepdog trials',
|
||||
date_from=date(2014, 7, 20), date_to=date(2014, 7, 21))
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
import django
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.core.exceptions import ValidationError, PermissionDenied
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.http import is_safe_url
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
@ -18,7 +16,6 @@ from wagtail.wagtailadmin import signals
|
||||
|
||||
from wagtail.wagtailcore import hooks
|
||||
from wagtail.wagtailcore.models import Page, PageRevision, get_navigation_menu_items
|
||||
|
||||
from wagtail.wagtailadmin import messages
|
||||
|
||||
|
||||
@ -145,8 +142,8 @@ def create(request, content_type_app_name, content_type_model_name, parent_page_
|
||||
form_class = edit_handler_class.get_form_class(page_class)
|
||||
|
||||
if request.POST:
|
||||
form = form_class(request.POST, request.FILES, instance=page)
|
||||
validate_page_form(form, parent_page)
|
||||
form = form_class(request.POST, request.FILES, instance=page,
|
||||
parent_page=parent_page)
|
||||
|
||||
if form.is_valid():
|
||||
page = form.save(commit=False)
|
||||
@ -236,8 +233,8 @@ def edit(request, page_id):
|
||||
errors_debug = None
|
||||
|
||||
if request.POST:
|
||||
form = form_class(request.POST, request.FILES, instance=page)
|
||||
validate_page_form(form, parent, page)
|
||||
form = form_class(request.POST, request.FILES, instance=page,
|
||||
parent_page=parent)
|
||||
|
||||
if form.is_valid() and not page.locked:
|
||||
page = form.save(commit=False)
|
||||
@ -315,48 +312,6 @@ def edit(request, page_id):
|
||||
})
|
||||
|
||||
|
||||
def validate_page_form(form, parent_page, instance=None):
|
||||
# Strip whitespace in title and seo_title fields
|
||||
# This is done for us in Django 1.9 and above
|
||||
if django.VERSION < (1, 9):
|
||||
def clean_title():
|
||||
return form.cleaned_data['title'].strip()
|
||||
|
||||
def clean_seo_title():
|
||||
return form.cleaned_data['seo_title'].strip()
|
||||
|
||||
form.clean_title = clean_title
|
||||
form.clean_seo_title = clean_seo_title
|
||||
|
||||
# Perform default validation
|
||||
form.full_clean()
|
||||
|
||||
if 'slug' in form.cleaned_data:
|
||||
# Get siblings for the page
|
||||
siblings = parent_page.get_children()
|
||||
if instance and instance.id:
|
||||
siblings = siblings.exclude(id=instance.id)
|
||||
|
||||
# Make sure the slug isn't being used by a sibling
|
||||
if siblings.filter(slug=form.cleaned_data['slug']).exists():
|
||||
form.add_error('slug', ValidationError(_("This slug is already in use")))
|
||||
|
||||
# Check scheduled publishing fields
|
||||
go_live_at = form.cleaned_data.get('go_live_at')
|
||||
expire_at = form.cleaned_data.get('expire_at')
|
||||
|
||||
# Go live must be before expire
|
||||
if go_live_at and expire_at:
|
||||
if go_live_at > expire_at:
|
||||
msg = _('Go live date/time must be before expiry date/time')
|
||||
form.add_error('go_live_at', ValidationError(msg))
|
||||
form.add_error('expire_at', ValidationError(msg))
|
||||
|
||||
# Expire at must be in the future
|
||||
if expire_at and expire_at < timezone.now():
|
||||
form.add_error('expire_at', ValidationError(_('Expiry date/time must be in the future')))
|
||||
|
||||
|
||||
def delete(request, page_id):
|
||||
page = get_object_or_404(Page, id=page_id)
|
||||
if not page.permissions_for_user(request.user).can_delete():
|
||||
@ -392,10 +347,11 @@ def preview_on_edit(request, page_id):
|
||||
page = get_object_or_404(Page, id=page_id).get_latest_revision_as_page()
|
||||
content_type = page.content_type
|
||||
page_class = content_type.model_class()
|
||||
parent_page = page.get_parent().specific
|
||||
edit_handler_class = page_class.get_edit_handler()
|
||||
form_class = edit_handler_class.get_form_class(page_class)
|
||||
|
||||
form = form_class(request.POST, request.FILES, instance=page)
|
||||
form = form_class(request.POST, request.FILES, instance=page, parent_page=parent_page)
|
||||
|
||||
if form.is_valid():
|
||||
form.save(commit=False)
|
||||
@ -429,14 +385,14 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
|
||||
page = page_class()
|
||||
edit_handler_class = page_class.get_edit_handler()
|
||||
form_class = edit_handler_class.get_form_class(page_class)
|
||||
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
||||
|
||||
form = form_class(request.POST, request.FILES, instance=page)
|
||||
form = form_class(request.POST, request.FILES, instance=page, parent_page=parent_page)
|
||||
|
||||
if form.is_valid():
|
||||
form.save(commit=False)
|
||||
|
||||
# ensure that our unsaved page instance has a suitable url set
|
||||
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
||||
page.set_url_path(parent_page)
|
||||
|
||||
# Set treebeard attributes
|
||||
@ -450,7 +406,6 @@ def preview_on_create(request, content_type_app_name, content_type_model_name, p
|
||||
|
||||
else:
|
||||
edit_handler = edit_handler_class(instance=page, form=form)
|
||||
parent_page = get_object_or_404(Page, id=parent_page_id).specific
|
||||
|
||||
response = render(request, 'wagtailadmin/pages/create.html', {
|
||||
'content_type': content_type,
|
||||
@ -669,8 +624,6 @@ def copy(request, page_id):
|
||||
})
|
||||
|
||||
|
||||
|
||||
|
||||
@vary_on_headers('X-Requested-With')
|
||||
def search(request):
|
||||
pages = []
|
||||
|
Loading…
Reference in New Issue
Block a user