Как правильно отобразить 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 %}
...

Вы можете редактировать и изменять псевдонимы независимо от ваших новостных статей.

Вернуться на верх