Как создать apphooks¶
apphook позволяет вам прикрепить Django-приложение к странице. Например, у вас может быть новостное приложение, которое вы хотели бы интегрировать с django CMS. В этом случае вы можете создать обычную страницу django CMS без собственного содержимого и прикрепить новостное приложение к этой странице; содержимое новостного приложения будет доставлено по URL страницы.
Все URL-адреса в этом пути URL будут переданы в URL-конфигурации подключенного приложения.
Раздел Tutorials содержит базовое руководство по getting started with apphooks. Этот документ предполагает большее знакомство с CMS в целом.
Основы создания apphook¶
Чтобы создать apphook, создайте файл cms_apps.py
в вашем приложении.
Файл должен содержать подкласс CMSApp
. Например:
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
@apphook_pool.register
class MyApphook(CMSApp):
app_name = "myapp" # must match the application namespace
name = "My Apphook"
def get_urls(self, page=None, language=None, **kwargs):
return ["myapp.urls"] # replace this with the path to your application's URLs module
Изменено в версии 3.3: CMSApp.get_urls()
заменяет CMSApp.urls
. urls
был удален в версии 3.5.
Apphooks для приложений с разграничением имен¶
Ваше приложение должно использовать namespaced URLs.
В приведенном выше примере приложение использует пространство имен myapp
. Ваш подкласс CMSApp
должен отражать пространство имен приложения в атрибуте app_name
.
Приложение может указать пространство имен, поставив app_name
в своем urls.py
, или его документация может рекомендовать, чтобы вы, когда включаете его URL, делали это таким образом:
re_path(r'^myapp/', include('myapp.urls', app_name='myapp'))
Если этого не сделать, то все шаблоны в приложении, вызывающие URL с помощью формы {% url 'myapp:index' %}
или представления, вызывающие (например) reverse('myapp:index')
, будут выдавать ошибку NoReverseMatch
.
Apphooks для неименованных приложений¶
Если вы пишете apphooks для сторонних приложений, вы можете встретить такое приложение, которое фактически не имеет пространства имен приложения для своих URL. Такое приложение может быть подвержено конфликтам пространств имен и не является примером хорошей практики.
Однако если вы действительно встретите такое приложение, ваш собственный apphook для него, в свою очередь, должен будет отказаться от атрибута app_name
.
Обратите внимание, что в отличие от apphooks без атрибутов app_name
могут быть прикреплены только к одной странице за один раз; попытка применить их во второй раз приведет к ошибке. Может существовать только один экземпляр этих apphooks.
Подробнее о наличии нескольких экземпляров apphook смотрите в Прикрепление приложения несколько раз.
Возвращение URL-адресов apphook вручную¶
Вместо того, чтобы определять шаблоны URL в другом файле myapp/urls.py
, можно также возвращать их вручную, например, если вам нужно переопределить предоставленный набор. Пример:
from django.urls import re_path
from myapp.views import SomeListView, SomeDetailView
class MyApphook(CMSApp):
# ...
def get_urls(self, page=None, language=None, **kwargs):
return [
re_path(r'^$', SomeListView.as_view()),
re_path(r'^(?P<slug>[\w-]+)/?$', SomeDetailView.as_view()),
]
Однако гораздо удобнее хранить их в urls.py
приложения, где они могут быть легко использованы повторно.
Загрузка новых и переконфигурированных apphooks¶
Некоторые изменения, связанные с apphook, требуют перезагрузки сервера для загрузки.
Когда бы вы ни были:
добавить или удалить apphook
изменить slug страницы, содержащей apphook, или slug страницы, у которой есть потомок с apphook
кэши URL должны быть перезагружены.
Если у вас установлен cms.middleware.utils.ApphookReloadMiddleware, что рекомендуется, сервер сделает это за вас, автоматически переинициализируя шаблоны URL.
В противном случае вам придется перезапустить сервер вручную.
Использование apphook¶
После настройки и загрузки apphook вы сможете выбрать приложение, которое подключено к этой странице, в ее расширенных настройках.
Примечание
apphook не будет ничего делать, пока страница, к которой он принадлежит, не будет опубликована. Обратите внимание, что это также означает, что все родительские страницы также должны быть опубликованы.
apphook прикрепляет все URL-адреса приложения apphooked к странице; корневой URL будет собственным URL-адресом страницы, а все URL-адреса более низкого уровня будут находиться на том же пути URL.
Итак, в приложении с urls.py
для представлений index_view
и archive_view
:
urlpatterns = [
re_path(r'^$', index_view),
re_path(r'^archive/$', archive_view),
]
прикрепленной к странице, путь URL которой /hello/world/
, представления будут открыты следующим образом:
index_view
при/hello/world/
archive_view
при/hello/world/archive/
Вложенные страницы страницы apphooked¶
Важно
Не добавляйте дочерние страницы к странице с apphook.
apphook «заглатывает» все URL ниже страницы, передавая их подключенному приложению. Если у вас есть дочерние страницы страницы apphooked, django CMS не сможет их надежно обслуживать.
Управление apphooks¶
Деинсталляция apphook с примененными экземплярами¶
Если вы удалите класс apphook из вашей системы (фактически деинсталлировав его), который все еще имеет экземпляры, применяемые к страницам, django CMS попытается справиться с этим настолько изящно, насколько это возможно:
На затронутых страницах сохраняется запись о примененном apphook; если класс apphook впоследствии будет восстановлен, он будет работать как прежде.
В списке страниц будут отображаться индикаторы apphook, где это необходимо.
В остальном страница будет вести себя как обычная страница django CMS, и отображать свои заполнители обычным образом.
Если вы сохраните Дополнительные настройки страницы, apphook будет удален.
Команды управления¶
Вы можете очистить неустановленные экземпляры apphook с помощью команды управления CMS uninstall apphooks
. Например:
manage.py cms uninstall apphooks MyApphook MyOtherApphook
Вы можете получить список установленных apphooks с помощью команды cms list; в данном случае:
manage.py cms list apphooks
Более подробную информацию см. в Management commands reference.
Управление разрешениями на apphooks¶
По умолчанию содержимое, представленное apphook, имеет те же разрешения, что и страница, к которой оно прикреплено. Поэтому, если, например, страница требует, чтобы пользователь вошел в систему, то прикрепленный apphook и все его URL будут иметь те же требования.
Чтобы отключить это поведение, установите permissions = False
в вашем apphook:
class MyApphook(CMSApp):
[...]
permissions = False
Если вы все еще хотите, чтобы некоторые из ваших представлений использовали проверки разрешений CMS, вы можете включить их с помощью декоратора, cms.utils.decorators.cms_perms
.
Вот простой пример:
from cms.utils.decorators import cms_perms
@cms_perms
def my_view(request, **kw):
...
Если вы делаете собственные проверки разрешений в своем приложении, то используйте свойство exclude_permissions
в apphook:
class MyApphook(CMSApp):
[...]
permissions = True
exclude_permissions = ["some_nested_app"]
где вы указываете название приложения, о котором идет речь
Автоматический перезапуск сервера при изменении apphook¶
Как упоминалось выше, всякий раз, когда вы:
добавить или удалить apphook
изменение slug страницы, содержащей apphook
изменение slug страницы с потомком с помощью apphook
CMS сервер будет перезагружать свои кэши URL. Для этого он прослушивает сигнал cms.signals.urls_need_reloading
.
Предупреждение
Этот сигнал сам по себе ничего не делает. Для автоматического перезапуска сервера вам необходимо реализовать в вашем проекте логику, которая будет выполняться каждый раз, когда сработает этот сигнал. Поскольку существует множество способов развертывания приложений Django, мы никак не можем предложить общее решение для этой проблемы, которое всегда будет работать.
Сигнал срабатывает после запроса - например, при сохранении настроек страницы. Если вы измените настройки apphook через API, сигнал не будет подан до следующего запроса.
Apphooks и тэги шаблонов¶
Важно понимать, что хотя apphooked приложение полностью берет на себя страницу CMS в этом месте, в зависимости от того, как шаблоны приложения расширяют другие шаблоны, тег шаблона django CMS {% placeholder %}
может быть вызван - но не будет работать.
С другой стороны, теги {% static_placeholder %}
не специфичны для страницы и будут функционировать нормально.