Django-CMS后台‘View on site’按钮反向匹配失败求助
解决Django 1.11 + django-cms中“view on site”按钮反向解析失败的问题
这个问题我之前也碰到过,核心原因是django-cms的apphook URL是绑定到特定CMS页面的,不属于全局URL路由,而admin的“view on site”默认依赖模型的get_absolute_url或直接反向解析URL,这时候缺少CMS页面的上下文,自然找不到对应的路由。
下面是几种靠谱的解决方式,按优先级推荐:
1. 重写模型的get_absolute_url方法(最通用)
直接在你的模型里生成带CMS页面上下文的完整URL,这样不管是admin的按钮还是前端调用,都能拿到正确的地址:
from django.core.urlresolvers import reverse from cms.models import Page from django.utils.translation import get_language class MyModel(models.Model): # 你的模型字段定义... def get_absolute_url(self): # 获取绑定了你的apphook的CMS页面(替换成你实际的apphook名称) # 如果有多语言,加上当前语言过滤更准确 page = Page.objects.filter( application_urls='MyApphook', language=get_language() ).first() if not page: # 兜底:如果找不到绑定的页面,返回admin修改页面的URL return reverse('admin:myapp_mymodel_change', args=[self.pk]) # 拼接页面URL和apphook内部的详情URL base_url = page.get_absolute_url() detail_path = reverse('myapp_mymodel_detail', args=[self.pk]) # 去掉detail_path开头的斜杠,避免出现//的情况 return f"{base_url}{detail_path.lstrip('/')}"
2. 自定义ModelAdmin的view_on_site方法(仅针对admin场景)
如果不想修改模型的get_absolute_url,可以直接在admin类里重写这个方法,专门处理admin的“view on site”逻辑:
from django.contrib import admin from django.core.urlresolvers import reverse from cms.models import Page from django.utils.translation import get_language from .models import MyModel class MyModelAdmin(admin.ModelAdmin): # 你的admin配置项... def view_on_site(self, obj): # 同样获取绑定apphook的CMS页面 page = Page.objects.filter( application_urls='MyApphook', language=get_language() ).first() if page: base_url = page.get_absolute_url() detail_path = reverse('myapp_mymodel_detail', args=[obj.pk]) return f"{base_url}{detail_path.lstrip('/')}" # 兜底逻辑 return reverse('admin:myapp_mymodel_change', args=[obj.pk])
3. 检查基础配置是否正确
在尝试上面的方法前,先确认两个基础问题:
- 你的apphook名称拼写正确:检查
application_urls参数和你注册apphook时的名称完全一致,大小写敏感。 - apphook的URLconf里,
myapp_mymodel_detail的name参数正确:比如你的app urls.py里要确保name是myapp_mymodel_detail,没有拼写错误:# myapp/urls.py from django.conf.urls import url from .views import MyModelDetailView urlpatterns = [ url(r'^detail/(?P<pk>\d+)/$', MyModelDetailView.as_view(), name='myapp_mymodel_detail'), ]
4. 多站点/多语言场景的优化
如果你的项目有多站点,记得在获取Page的时候加上站点过滤:
# 假设你的模型有site字段 page = Page.objects.filter( application_urls='MyApphook', language=get_language(), site=obj.site ).first()
这样处理后,admin的“view on site”按钮就能正确跳转到前端的详情页面了。
内容的提问来源于stack exchange,提问作者Beniamino Nobile
相关产品推荐
相关产品推荐

