未定义 Django 自定义管理 url

Posted

技术标签:

【中文标题】未定义 Django 自定义管理 url【英文标题】:Django custom admin urls not defined 【发布时间】:2013-02-16 11:15:23 【问题描述】:

我正在尝试向模型管理员添加两个 URL。

class JobTitleAdmin(admin.ModelAdmin):
    inlines = [OccupationTagInline, ]
    model = JobTitle
    search_fields = ['title',]
    list_filter = ['status',]
    actions =['add_to_job_category', 'move_to_job_category' ]

    def add_to_job_category_view(self, request):

        return render_to_response(
            'admin/job_title/select_job_category.html',
            
                'action': 'add',
                'featured_occupations': Occupation.objects.filter(featured=True),
                'title_ids': array(request.GET['foo'])
                ,
            context_instance=RequestContext(request)
            )

    def get_urls(self):
        urls = super(JobTitleAdmin, self).get_urls()
        custom_urls = patterns('',
            url(r'^add_to_job_category/$', self.admin_site.admin_view(self.add_to_job_category_view), name='admin_jobtitle_add_to_cat',),
            url(r'^move_to_job_category/$', self.admin_site.admin_view(self.move_to_job_category_view), name='admin_jobtitle_move_to_cat',)
    )

        return custom_urls + urls

为简单起见,我省略了视图代码。

这两种模式没有定义,因为如果我尝试访问它们并且没有在 django debud 404 页面中列出,我会得到 404。然而 get_urls 方法被正确调用(实际上是两次,不知道为什么)。

可能出了什么问题?

【问题讨论】:

我们能看到其余代码的准确性吗?具体来说,您正在使用的两个视图函数。 我刚做了。另一个观点几乎相同。我还没有写完整的视图,因为我可以得到它。 你确定你得到的是 404 而不是某种类型的 500?另外,您尝试访问它们的网址是什么? 注意:自定义 URL 附加到父 ModelAdmin URL。对于上面的示例,URL 将是/admin/app-name/JobTitleAdmin/add_to_job_category/。这在 Django 文档Note 中有所介绍。此外,自定义 URL 不会列在 Django 调试 404 页面中。 【参考方案1】:

我已经成功完成了这个,但是我复制了 ModelAdmin.get_urls wrap 装饰器。也许试试:

from functools import update_wrapper
class JobTitleAdmin(admin.ModelAdmin):
    inlines = [OccupationTagInline, ]
    model = JobTitle
    search_fields = ['title',]
    list_filter = ['status',]
    actions =['add_to_job_category', 'move_to_job_category' ]

    def add_to_job_category_view(self, request):

        return render_to_response(
            'admin/job_title/select_job_category.html',
            
                'action': 'add',
                'featured_occupations': Occupation.objects.filter(featured=True),
                'title_ids': array(request.GET['foo'])
                ,
            context_instance=RequestContext(request)
            )

    def get_urls(self):
        urls = super(JobTitleAdmin, self).get_urls()

        def wrap(view):
            def wrapper(*args, **kwargs):
                return self.admin_site.admin_view(view)(*args, **kwargs)
            return update_wrapper(wrapper, view)

        custom_urls = patterns('',
            url(r'^add_to_job_category/$',
                 wrap(self.add_to_job_category_view),
                 name='admin_jobtitle_add_to_cat',),
            url(r'^move_to_job_category/$',
                 wrap(self.move_to_job_category_view),
                 name='admin_jobtitle_move_to_cat',)
        )

        return custom_urls + urls

【讨论】:

有趣。那是作为“包装”导演的确切dsmr代码吗?无论如何,这立即奏效了。仍然不知道为什么。 什么是dsmr?我也不完全确定为什么这也有效。 docs 说 update_wrapper 使 wrapper 函数签名匹配 wrapped 函数。我想通过直接用admin_view 包装你的视图,url 解析器希望你的方法具有(self, view, cacheable=False) 参数签名。 dsmr = 写得太快,没有查看我的回复。 我认为wrap() hack 是一个红鲱鱼。通过遵循example in the Django docs(使用v1.8 测试),我能够使自定义URL 正常工作。我的视图方法签名是admin_jobtitle_add_to_cat(self, request, *args, **kwargs)(它需要pk kwarg)。【参考方案2】:

从您的代码看来,您正在尝试将一些 action intermediate views 添加到您的 ModelAdmin 类中。

这是通过将函数名称放在actions 属性中来实现的。如果您只是添加自定义操作,则无需添加自定义 url。您的示例可以这样修改:

class JobTitleAdmin(admin.ModelAdmin):
    inlines = [OccupationTagInline, ]
    model = JobTitle
    search_fields = ['title',]
    list_filter = ['status',]
    actions =['add_to_job_category', 'move_to_job_category' ]

    def add_to_job_category(self, request, queryset):

        return render_to_response(
            'admin/job_title/select_job_category.html',
            
                'action': 'add',
                'featured_occupations': Occupation.objects.filter(featured=True),
                'title_ids': array(request.GET['foo'])  # <-- this would probably be changed to use `queryset` function argument
                ,
            context_instance=RequestContext(request)
            )
    add_to_job_category.short_description = "Add to job category"

ModelAdmin 类将知道如何调用您的自定义函数并将操作添加到操作下拉列表中。中间响应视图add_to_job_category 需要知道如何从操作中获取输入以确定选择了哪些项目。

如果您真的想添加自定义 url,那么您的 get_urls() 函数似乎是正确的。注意get_urls返回的url是相对于admin/&lt;app&gt;/&lt;model&gt;的。

如果您的应用被命名为myapp 并且您的模型被命名为JobTitle,那么访问add_to_job_category 视图的网址将是:

http://some.site/admin/myapp/jobtitle/add_to_job_category/

【讨论】:

谢谢。动作部分很好,工作正常。问题实际上是为额外的视图添加新的 url。 现在我将 URL 添加到根 urls.py 文件中,但这不是很干净,也不是应该的方式。 你能给出一个给出 404 的完整示例 URL 吗?

以上是关于未定义 Django 自定义管理 url的主要内容,如果未能解决你的问题,请参考以下文章

Django 自定义用户创建未在管理站点中显示自定义字段

管理面板中未调用 Django 自定义用户管理器

自定义注销页面未登陆

自定义静态文件未在 django 项目中加载

自定义页面 404 未显示,但页面 500 正在显示

Url.Action 未输出自定义映射控制器路由