【问题标题】:build_absolute_uri in Django admin (for a list_display field)Django admin 中的 build_absolute_uri(用于 list_display 字段)
【发布时间】:2013-03-12 19:33:00
【问题描述】:

我正在尝试在 Django 管理员的列表显示中显示绝对 URI:

from django.contrib import admin
class MyAdmin(admin.ModelAdmin):
    list_display = (
        'full_uri',
    )

    readonly_fields = (
        'full_uri',
    )

    def full_uri(self, obj):
        return u'<a href="{url}">{url}'.format(
            url = request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
        )
    full_uri.allow_tags = True

问题 - 我无权访问请求对象(其中定义了 build_absolute_uri)。

我尝试覆盖 changelist_view 并在本地存储请求,但这不是 thread safe

我也试过this解决方案,但不是很优雅。

还有其他想法吗?

编辑:

这是一个安全的解决方案吗:

def changelist_view(self, request, extra_context=None):
    self.request = request
    try:
        return super(MyAdmin,self).changelist_view(request, extra_context=extra_context)
    finally:
        self.request = None

EDIT2:

根本不是线程安全的! 12,...

【问题讨论】:

    标签: django django-admin


    【解决方案1】:

    每个扩展 admin.ModelAdmin 的类都有两个可以覆盖的函数:change_view 和 changelist_view。 change_view在编辑单个实例时调用,changelist_view在查看所有项目列表时调用。

    这两个函数充当管理员的视图定义并包含页面的请求对象。这意味着在这两个函数中,您可以将请求存储为self 的属性,以使其可供从该视图调用的类中的其他函数访问。话虽如此,这样的事情应该可以工作:

    from django.contrib import admin
    class MyAdmin(admin.ModelAdmin):
    list_display = (
        'full_uri',
    )
    
    readonly_fields = (
        'full_uri',
    )
    
    def change_view(self, request, object_id, form_url='', extra_context=None):
        # access the request object when in the change view
        self.request = request
        return super(MyAdmin, self).change_view(request, object_id, form_url=form_url, extra_context=extra_context)
    
    def changelist_view(self, request, extra_context=None):
        # access the request object when in the list view
        self.request = request
        return super(MyAdmin,self).changelist_view(request, extra_context=extra_context)
    
    def full_uri(self, obj):
        return u'<a href="{url}">{url}'.format(
            # access the request object through self.request, as set by the two view functions
            url = self.request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
        )
    full_uri.allow_tags = True
    

    【讨论】:

    • 好吧,我想如果我们用 try-finally 包围它,这样做可能没问题。
    • 我不知道你为什么需要尝试包装对 super 的调用。我以前从未这样做过。
    • 由于ModelAdmin实例被不同的请求使用,不建议更改它们的状态。最后是确保无论如何都进行清理。
    • 对不起。在进一步挖掘之后,我不得不接受你的回答,因为它真的是线程不安全的。我想我找到了一种方法来做到这一点..
    【解决方案2】:

    我想我找到了一种以线程安全的方式执行此操作的方法,在 get_list_display 中创建一个函数:

    def get_list_display(self, request):
    
       def link_to_view(obj):
            return u'<a href="{url}">{url}'.format(
                url = request.build_absolute_uri(reverse('view_name', args=(obj, )))
            )
        token_access_link.short_description = _('link')
        token_access_link.allow_tags = True
    
        return (
            link_to_view,
        )
    

    【讨论】:

      【解决方案3】:

      如果我对问题的理解正确,您只需要在尚未发送的函数中访问请求对象即可?

      如果是这样,我发现django-globals 是最有帮助的,因为它提供了对当前请求和用户的通用访问(默认情况下应该可以访问,就像在烧瓶中一样!)

      pip install django-globals
      

      settings.py

      INSTALLED_APPS = [
         ...
         'django_globals'
      ]
      MIDDLEWARE_CLASSES = [
          ...
          'django_globals.middleware.Global'
      ]
      

      view.py

      from django_globals import globals as djglobals
      
      def myfunc():
          djglobals.user
          djglobals.request
      

      【讨论】:

        猜你喜欢
        • 2013-03-07
        • 2012-01-08
        • 1970-01-01
        • 2019-07-28
        • 2017-09-02
        • 1970-01-01
        • 1970-01-01
        • 2017-08-25
        • 1970-01-01
        相关资源
        最近更新 更多