如何通过模型slug更好地关联Django模型与Django CMS页面/占位符?
如何通过模型slug更好地关联Django模型与Django CMS页面/占位符?
嘿,我明白你的需求了——给每个News条目配上一段用Django CMS编辑的HTML片段,还想用slug来关联两者,这个场景很常见,我来给你梳理几个靠谱的方案,帮你解决之前遇到的问题:
方案一:通过slug匹配关联Django CMS Page和News模型
你之前尝试直接取CMS Page但没成功,大概率是没找对获取页面内容的方式。这个方案的核心是让News的slug和对应CMS Page的slug完全一致,以此建立关联:
- 第一步:在Django CMS后台创建Page时,把Page的slug设置成和对应News条目的slug完全相同,比如News的slug是
2024-new-product-launch,那CMS Page的slug也设成这个值。同时给这个Page添加一个专属的slot(比如叫news_extra_content),用来存放你需要的HTML片段。 - 第二步:在News详情视图里,通过slug同时获取News实例和对应的CMS Page:
from django.core.exceptions import ObjectDoesNotExist from django.shortcuts import get_object_or_404, render from cms.models import Page from .models import News def news_detail(request, slug): news = get_object_or_404(News, slug=slug) extra_placeholder = None try: # 只取已发布的CMS Page cms_page = Page.objects.published().get(slug=slug) # 获取指定slot的占位符 extra_placeholder = cms_page.placeholders.get(slot="news_extra_content") except ObjectDoesNotExist: # 如果没有对应的CMS Page,就留空 pass return render(request, 'news/detail.html', { 'news': news, 'extra_placeholder': extra_placeholder, }) - 第三步:在模板里渲染占位符内容:
{% load cms_tags %} <!-- 显示News模型的基础内容 --> <h1>{{ news.title }}</h1> <div class="news-content">{{ news.content }}</div> <!-- 显示CMS编辑的HTML片段 --> {% if extra_placeholder %} <div class="news-extra"> {% render_placeholder extra_placeholder %} </div> {% endif %}
方案二:给News模型直接添加内置占位符(推荐)
这个方案比slug匹配更省心,不需要单独管理CMS Page,直接把CMS的编辑能力嵌入到News模型里,天然和News实例关联:
- 第一步:修改News模型,添加
PlaceholderField:from django.db import models from cms.models.fields import PlaceholderField class News(models.Model): title = models.CharField(max_length=200) slug = models.SlugField(unique=True) content = models.TextField() # 添加专属占位符,指定slot名称 extra_content = PlaceholderField('news_extra_content') def __str__(self): return self.title - 第二步:在Django Admin里注册News模型时,继承
PlaceholderAdminMixin,让管理员能在编辑News时直接用CMS编辑器:from django.contrib import admin from cms.admin.placeholderadmin import PlaceholderAdminMixin from .models import News @admin.register(News) class NewsAdmin(PlaceholderAdminMixin, admin.ModelAdmin): list_display = ('title', 'slug') prepopulated_fields = {'slug': ('title',)} # 自动从标题生成slug - 第三步:在模板里直接渲染占位符:
{% load cms_tags %} <h1>{{ news.title }}</h1> <div class="news-content">{{ news.content }}</div> <!-- 直接渲染News模型自带的CMS占位符 --> <div class="news-extra"> {% render_placeholder news.extra_content %} </div>
这个方案的优势是:所有内容都在News的编辑界面完成,不需要额外维护CMS Page,关联关系天然存在,完全不用依赖slug匹配,管理员操作也更直观。
方案三:Apphooks(适合复杂扩展场景)
你之前觉得Apphooks可能不适合,这个判断其实没错——如果只是需要一段HTML片段,前面两个方案更轻量。但如果未来你的News模块需要更多CMS特性(比如自定义导航、权限控制、多语言支持等),Apphooks可以考虑:
核心思路是创建一个CMS Apphook关联你的News应用,然后在CMS里创建一个父Page挂载这个Apphook,再给每个News条目创建对应的CMS子Page,子Page的slug和News的slug保持一致。不过这个方式配置相对复杂,适合有更多CMS功能需求的场景。
备注:内容来源于stack exchange,提问作者Pendelbus
相关产品推荐
相关产品推荐

