我有一些自定义逻辑(复杂的唯一性约束验证),我想检查用户何时尝试在Wagtail中复制(或移动)某种类型的Page。我还想给用户一个机会来更改与验证检查关联的字段。
我知道Wagtail公开了一种通过钩子(http://docs.wagtail.io/en/stable/reference/hooks.html#before-copy-page来定制复制(和移动)体验的方式,但是我能使用该工具的最好的方法是创建一个全新的接口,并在HttpResponse中返回它。有没有一种方法可以仅针对特定页面类型自定义现有的复制(和移动)界面?
@hooks.register('before-copy-page')
def before-copy-page(request, page):
return HttpResponse("New copy interface", content_type="text/plain")
答案 0 :(得分:1)
这三种方法可让您更深入地了解Wagtail页面复制视图和验证的自定义。您可能不需要全部执行这三个操作,但是下面的示例代码假定所有更改都已在某种程度上完成。
也许会有更好的方法来完成您想要的事情,但是希望这为您提供了一些方法来自定义整个副本视图/表单交互的一部分。
这些方法应该适用于移动页面交互,但是还有更多的表单和视图。
templates/wagtailadmin/pages/copy.html
处添加模板将覆盖copy page form template。{% extends "wagtailadmin/pages/copy.html" %}
来轻松扩展复制页面的原始模板,这省去了复制/粘贴大部分页面的麻烦,并且仅自定义了所需的块。{{ block.super }}
在这里很方便。admin/
网址上方添加新的URL路径,将首先对其进行访问。url(r'^admin/pages/(\d+)/copy/$', base_views.customCopy, name='copy'),
,这会将管理员副本页面定向到我们的customCopy
视图。CopyForm
CopyForm
并自定义其__init__
或clean
方法(或根据需要的任何其他方法)。CopyForm
的源代码来查看需要修改的内容,如果要向表单中添加字段,则需要这样做(以及模板更改)。{% extends "wagtailadmin/pages/copy.html" %}
{% load i18n %}
{% block content %}
{% comment %} source - wagtail/admin/templates/wagtailadmin/pages/copy.html {% endcomment %}
{% trans "Copy" as copy_str %}
{% include "wagtailadmin/shared/header.html" with title=copy_str subtitle=page.get_admin_display_title icon="doc-empty-inverse" %}
<div class="nice-padding">
<form action="{% url 'wagtailadmin_pages:copy' page.id %}" method="POST" novalidate>
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}" />
<ul class="fields">
{% include "wagtailadmin/shared/field_as_li.html" with field=form.new_title %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.new_slug %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.new_parent_page %}
{% if form.copy_subpages %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.copy_subpages %}
{% endif %}
{% if form.publish_copies %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.publish_copies %}
{% endif %}
{% comment %} BEGIN CUSTOM CONTENT {% endcomment %}
{% include "wagtailadmin/shared/field_as_li.html" with field=form.other %}
{% comment %} END CUSTOM CONTENT {% endcomment %}
</ul>
<input type="submit" value="{% trans 'Copy this page' %}" class="button">
</form>
</div>
{% endblock %}
from django.conf.urls import include, url
from django.contrib import admin
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.admin.views import pages
from wagtail.documents import urls as wagtaildocs_urls
from wagtail.core import urls as wagtail_urls
from myapp.base import views as base_views # added
urlpatterns = [
url(r'^django-admin/', admin.site.urls),
url(r'^admin/pages/(\d+)/copy/$', base_views.customCopy, name='copy'), # added
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'', include(wagtail_urls)),
]
from django import forms
from django.core.exceptions import PermissionDenied
from wagtail.admin.forms.pages import CopyForm
from wagtail.admin.views import pages
from wagtail.core.models import Page
# BEGIN monkey patch of CopyForm
# See: wagtail/admin/forms/pages.py
original_form_init = CopyForm.__init__
original_form_clean = CopyForm.clean
def custom_form_init(self, *args, **kwargs):
# note - the template will need to be overridden to show additional fields
original_form_init(self, *args, **kwargs)
self.fields['other'] = forms.CharField(initial="will fail", label="Other", required=False)
def custom_form_clean(self):
cleaned_data = original_form_clean(self)
other = cleaned_data.get('other')
if other == 'will fail':
self._errors['other'] = self.error_class(["This field failed due to custom form validation"])
del cleaned_data['other']
return cleaned_data
CopyForm.__init__ = custom_form_init
CopyForm.clean = custom_form_clean
# END monkey patch of CopyForm
def customCopy(request, page_id):
"""
here we can inject any custom code for the response as a whole
the template is a view function so we cannot easily customise it
we can respond to POST or GET with any customisations though
See: wagtail/admin/views/pages.py
"""
page = Page.objects.get(id=page_id)
# Parent page defaults to parent of source page
parent_page = page.get_parent()
# Check if the user has permission to publish subpages on the parent
can_publish = parent_page.permissions_for_user(request.user).can_publish_subpage()
# Create the form
form = CopyForm(request.POST or None, user=request.user, page=page, can_publish=can_publish)
if request.method == 'POST':
if form.is_valid():
# if the form has been validated (using the form clean above)
# we get another chance here to fail the request, or redirect to another page
# we can also easily access the specific page's model for any Page model methods
try:
if not page.specific.can_copy_check():
raise PermissionDenied
except AttributeError:
# continue through to the normal behaviour
pass
response = pages.copy(request, page_id)
return response