未定义 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的主要内容,如果未能解决你的问题,请参考以下文章