kopia lustrzana https://github.com/wagtail/wagtail
Allow specifying custom edit handlers for snippets
rodzic
ca343e2358
commit
3f2f5665b0
|
@ -5,6 +5,7 @@ Changelog
|
|||
~~~~~~~~~~~~~~~~
|
||||
|
||||
* The `Document` model can now be overridden using the new `WAGTAILDOCS_DOCUMENT_MODEL` setting (Alex Gleason)
|
||||
* Snippets now support a custom `edit_handler` property (Mikalai Radchuk)
|
||||
* Date/time pickers now respect the locale's 'first day of week' setting (Peter Quade)
|
||||
* Refactored the way forms are constructed for the page editor, to allow custom forms to be used
|
||||
* Notification message on publish now indicates whether the page is being published now or scheduled for publication in future (Chris Rogers)
|
||||
|
|
|
@ -102,6 +102,7 @@ Contributors
|
|||
* Matt Fozard
|
||||
* Chris Rogers
|
||||
* Josh Schneier
|
||||
* Mikalai Radchuk
|
||||
|
||||
|
||||
Translators
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
Customising the page editing interface
|
||||
======================================
|
||||
Customising the editing interface
|
||||
=================================
|
||||
|
||||
.. _customising_the_tabbed_interface:
|
||||
|
||||
|
@ -8,7 +8,7 @@ Customising the tabbed interface
|
|||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
As standard, Wagtail organises panels into three tabs: 'Content', 'Promote' and 'Settings'. Depending on the requirements of your site, you may wish to customise this for specific page types - for example, adding an additional tab for sidebar content. This can be done by specifying an ``edit_handler`` property on the page model. For example:
|
||||
As standard, Wagtail organises panels for pages into three tabs: 'Content', 'Promote' and 'Settings'. For snippets Wagtail puts all panels into one page. Depending on the requirements of your site, you may wish to customise this for specific page types or snippets - for example, adding an additional tab for sidebar content. This can be done by specifying an ``edit_handler`` attribute on the page or snippet model. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ The `Document` model can now be overridden using the new `WAGTAILDOCS_DOCUMENT_M
|
|||
Minor features
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
* Snippets now support a custom ``edit_handler`` property; this can be used to implement a tabbed interface, for example. See :ref:`customising_the_tabbed_interface` (Mikalai Radchuk)
|
||||
* Date/time pickers now respect the locale's 'first day of week' setting (Peter Quade)
|
||||
* Refactored the way forms are constructed for the page editor, to allow custom forms to be used
|
||||
* Notification message on publish now indicates whether the page is being published now or scheduled for publication in future (Chris Rogers)
|
||||
|
|
|
@ -706,6 +706,15 @@
|
|||
"url": "http://www.example.com"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "tests.advertwithtabbedinterface",
|
||||
"fields": {
|
||||
"text": "test_advert",
|
||||
"url": "http://www.example.com",
|
||||
"something_else": "Model with tabbed interface"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "wagtaildocs.Document",
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tests', '0023_mycustompage'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='AdvertWithTabbedInterface',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('url', models.URLField(null=True, blank=True)),
|
||||
('text', models.CharField(max_length=255)),
|
||||
('something_else', models.CharField(max_length=255)),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -0,0 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9.1 on 2016-01-28 12:53
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tests', '0024_validatedpage'),
|
||||
('tests', '0024_advertwithtabbedinterface'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
]
|
|
@ -371,6 +371,33 @@ class Advert(ClusterableModel):
|
|||
register_snippet(Advert)
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class AdvertWithTabbedInterface(models.Model):
|
||||
url = models.URLField(null=True, blank=True)
|
||||
text = models.CharField(max_length=255)
|
||||
something_else = models.CharField(max_length=255)
|
||||
|
||||
advert_panels = [
|
||||
FieldPanel('url'),
|
||||
FieldPanel('text'),
|
||||
]
|
||||
|
||||
other_panels = [
|
||||
FieldPanel('something_else'),
|
||||
]
|
||||
|
||||
edit_handler = TabbedInterface([
|
||||
ObjectList(advert_panels, heading='Advert'),
|
||||
ObjectList(other_panels, heading='Other'),
|
||||
])
|
||||
|
||||
def __str__(self):
|
||||
return self.text
|
||||
|
||||
|
||||
register_snippet(AdvertWithTabbedInterface)
|
||||
|
||||
|
||||
class StandardIndex(Page):
|
||||
""" Index for the site """
|
||||
parent_page_types = [Page]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block titletag %}{% blocktrans with snippet_type_name=model_opts.verbose_name %}New {{ snippet_type_name }}{% endblocktrans %}{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "New" as new_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=new_str subtitle=model_opts.verbose_name icon="snippet" %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=new_str subtitle=model_opts.verbose_name icon="snippet" tabbed=1 merged=1 %}
|
||||
|
||||
<form action="{% url 'wagtailsnippets:add' model_opts.app_label model_opts.model_name %}" method="POST">
|
||||
{% csrf_token %}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{% block titletag %}{% blocktrans with snippet_type_name=model_opts.verbose_name %}Editing {{ snippet_type_name }} - {{ instance }}{% endblocktrans %}{% endblock %}
|
||||
{% block content %}
|
||||
{% trans "Editing" as editing_str %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=instance icon="snippet" usage_object=instance %}
|
||||
{% include "wagtailadmin/shared/header.html" with title=editing_str subtitle=instance icon="snippet" usage_object=instance tabbed=1 merged=1 %}
|
||||
|
||||
<form action="{% url 'wagtailsnippets:edit' model_opts.app_label model_opts.model_name instance.id %}" method="POST">
|
||||
{% csrf_token %}
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from taggit.models import Tag
|
||||
|
||||
from wagtail.tests.utils import WagtailTestUtils
|
||||
from wagtail.tests.testapp.models import Advert, SnippetChooserModel
|
||||
from wagtail.tests.testapp.models import Advert, SnippetChooserModel, AdvertWithTabbedInterface
|
||||
from wagtail.tests.snippets.models import (
|
||||
AlphaSnippet, ZuluSnippet, RegisterDecorator, RegisterFunction, SearchableSnippet
|
||||
)
|
||||
|
@ -131,6 +131,19 @@ class TestSnippetCreateView(TestCase, WagtailTestUtils):
|
|||
response = self.get()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'wagtailsnippets/snippets/create.html')
|
||||
self.assertNotContains(response, '<ul class="tab-nav merged">')
|
||||
self.assertNotContains(response, '<a href="#advert" class="active">Advert</a>', html=True)
|
||||
self.assertNotContains(response, '<a href="#other" class="">Other</a>', html=True)
|
||||
|
||||
def test_snippet_with_tabbed_interface(self):
|
||||
response = self.client.get(reverse('wagtailsnippets:add',
|
||||
args=('tests', 'advertwithtabbedinterface')))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'wagtailsnippets/snippets/create.html')
|
||||
self.assertContains(response, '<ul class="tab-nav merged">')
|
||||
self.assertContains(response, '<a href="#advert" class="active">Advert</a>', html=True)
|
||||
self.assertContains(response, '<a href="#other" class="">Other</a>', html=True)
|
||||
|
||||
def test_create_invalid(self):
|
||||
response = self.post(post_data={'foo': 'bar'})
|
||||
|
@ -169,6 +182,7 @@ class TestSnippetEditView(TestCase, WagtailTestUtils):
|
|||
|
||||
def setUp(self):
|
||||
self.test_snippet = Advert.objects.get(id=1)
|
||||
self.test_snippet_with_tabbed_interface = AdvertWithTabbedInterface.objects.get(id=1)
|
||||
self.login()
|
||||
|
||||
def get(self, params={}):
|
||||
|
@ -185,6 +199,19 @@ class TestSnippetEditView(TestCase, WagtailTestUtils):
|
|||
response = self.get()
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'wagtailsnippets/snippets/edit.html')
|
||||
self.assertNotContains(response, '<ul class="tab-nav merged">')
|
||||
self.assertNotContains(response, '<a href="#advert" class="active">Advert</a>', html=True)
|
||||
self.assertNotContains(response, '<a href="#other" class="">Other</a>', html=True)
|
||||
|
||||
def test_snippet_with_tabbed_interface(self):
|
||||
reverse_args = ('tests', 'advertwithtabbedinterface', self.test_snippet_with_tabbed_interface.id)
|
||||
response = self.client.get(reverse('wagtailsnippets:edit', args=reverse_args))
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertTemplateUsed(response, 'wagtailsnippets/snippets/edit.html')
|
||||
self.assertContains(response, '<ul class="tab-nav merged">')
|
||||
self.assertContains(response, '<a href="#advert" class="active">Advert</a>', html=True)
|
||||
self.assertContains(response, '<a href="#other" class="">Other</a>', html=True)
|
||||
|
||||
def test_non_existant_model(self):
|
||||
response = self.client.get(reverse('wagtailsnippets:edit', args=('tests', 'foo', self.test_snippet.id)))
|
||||
|
|
|
@ -40,10 +40,14 @@ SNIPPET_EDIT_HANDLERS = {}
|
|||
|
||||
def get_snippet_edit_handler(model):
|
||||
if model not in SNIPPET_EDIT_HANDLERS:
|
||||
panels = extract_panel_definitions_from_model_class(model)
|
||||
edit_handler = ObjectList(panels).bind_to_model(model)
|
||||
if hasattr(model, 'edit_handler'):
|
||||
# use the edit handler specified on the page class
|
||||
edit_handler = model.edit_handler
|
||||
else:
|
||||
panels = extract_panel_definitions_from_model_class(model)
|
||||
edit_handler = ObjectList(panels)
|
||||
|
||||
SNIPPET_EDIT_HANDLERS[model] = edit_handler
|
||||
SNIPPET_EDIT_HANDLERS[model] = edit_handler.bind_to_model(model)
|
||||
|
||||
return SNIPPET_EDIT_HANDLERS[model]
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue