Как правильно отобразить django-view с помощью Apphooks в django-cms?
Я создаю проект на Django CMS, используя версию 4.1.2. Частью проекта будет новостной раздел, для которого я определил Django-модель следующим образом:
# news/models.py
from django.db import models
from django.utils import timezone
from djangocms_text_ckeditor.fields import HTMLField
class Post(models.Model):
title = models.CharField(max_length=200, verbose_name="Title")
text = HTMLField(verbose_name="Text")
user = models.ForeignKey('auth.User', on_delete=models.CASCADE, verbose_name="Author", blank=True, null=True)
date = models.DateTimeField(default=timezone.now, verbose_name="Date")
class Meta:
verbose_name = "Post"
verbose_name_plural = "Posts"
def __str__(self):
return self.title
Я хочу, чтобы эта модель была моделью django, а не обрабатывалась CMS-плагинами, чтобы редакторы могли управлять постами с помощью админ-интерфейса и чтобы было проще использовать такие вещи, как пагинация. У меня есть небольшой опыт работы с Django, но не совсем с Django CMS.
Однако на странице, отображающей раздел новостей, я также хочу иметь заголовок, боковую панель и нижний колонтитул, которые должны редактироваться с помощью CMS-Toolbar. Поэтому я сделал Apphook - насколько я понимаю, это должно позволить мне интегрировать страницу новостей с Django CMS. Вот как выглядит мой Apphook:
# news/cms_apps.py
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
from django.urls import path
from django.utils.translation import gettext_lazy as _
from news import views
@apphook_pool.register
class NewsApp(CMSApp):
app_name = "news_app"
name = _("News Application")
def get_urls(self, page=None, language=None, **kwargs):
return [
path("news/", views.news_view, name="news"),
]
Представление, которое должно быть вызвано этим Apphook, выглядит следующим образом:
# news/views.py
from django.shortcuts import render
from .models import Post
def news_view(request):
posts = Post.objects.all().order_by('-date')
print("Number of posts:", posts.count())
context = {
'posts': posts,
}
return render(request, 'news.html', context)
Минимальный пример шаблона news.html
выглядит так:
{% extends "base.html" %}
{% load cms_tags sekizai_tags %}
{% load djangocms_alias_tags %}
{% block title %}News{% endblock %}
{% block header %}
{% placeholder "header_placeholder" %}
{% endblock %}
{% block content %}
<h1>News</h1>
{% for post in posts %}
{{ post.title }}
{% endfor %}
<p>End of news</p>
{% endblock %}
В панели администратора я создал страницу "Новости" с именем news/
. В расширенных настройках этой страницы я выбрал Apphook. В качестве шаблона для этой страницы я выбрал news.html
, который также объявлен в settings.py
:
# settings.py
CMS_TEMPLATES = [
('home.html', 'Content Template'),
('news.html', 'Newspage Template'),
]
При всей этой установке я ожидал, что представление передаст пост-данные шаблону, который затем отрисует их - в случае минимального примера между <h1>News</h1>
и <p>End of news</p>
. Однако этого не происходит. Между этими тегами ничего не отображается, и кажется, что шаблону вообще не передаются данные, поскольку я также не вижу print
-результатов от представления.
Изменение метода get_urls()
в Apphook на такой приводит к тому, что шаблон отображается, как и ожидалось, но без возможности редактирования в CMS:
def get_urls(self, page=None, language=None, **kwargs):
return [
path("", views.news_view, name="news"),
]
Может ли кто-нибудь указать мне правильное направление для решения этой проблемы? Я не очень понимаю, что здесь происходит, и я не смог найти ничего об этом в документации... Спасибо!
Тег шаблона placeholder
работает только на страницах django CMS.
Вероятно, вам нужен общий заголовок для всех новостей. Возможно, вам стоит обратить внимание на пакет djangocms-alias, он позволяет определять многократно используемый контент.
Замените шаблонный тег placeholder
на static_alias
:
{% load djangocms_alias_tags %}
...
{% block header %}
{% static_placeholder "header_placeholder" %}
{% endblock %}
...
Вы можете редактировать и изменять псевдонимы независимо от ваших новостных статей.