Django admin中的build_absolute_uri(对于list_display字段)

时间:2013-03-12 19:33:00

标签: django django-admin

我正在尝试在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并存储请求localy,但这不是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:

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

3 个答案:

答案 0 :(得分:3)

每个扩展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

答案 1 :(得分:1)

我想我找到了一种以线程安全方式完成它的方法,在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,
    )

答案 2 :(得分:0)

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

如果是这样,我发现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