在Django admin中构建绝对uri(用于列表显示字段)

在Django admin中构建绝对uri(用于列表显示字段),django,django-admin,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=

我试图在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
EDIT2:


根本不是线程安全的

每个扩展admin.ModelAdmin的类都有两个可以覆盖的函数:change\u视图和changelist\u视图<编辑单个实例时调用“代码>更改”视图,查看所有项目列表时调用“代码>更改列表”视图

这两个函数充当管理员的视图定义,并包含页面的请求对象。这意味着在这两个函数中,您可以将请求存储为
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
来自django.contrib导入管理
类MyAdmin(admin.ModelAdmin):
列表显示=(
“完整uri”,
)
只读_字段=(
“完整uri”,
)
def change_视图(自身、请求、对象id、表单url=''、额外上下文=None):
#在“更改”视图中访问请求对象
self.request=请求
返回super(MyAdmin,self)。更改视图(请求,对象id,表单url=表单url,额外上下文=额外上下文)
def变更列表视图(自身、请求、额外上下文=无):
#在列表视图中访问请求对象
self.request=请求
返回super(MyAdmin,self).changelist\u视图(请求,额外上下文=额外上下文)
def full_uri(自身、obj):
返回u'{url}'。格式(
#通过两个视图函数设置的self.request访问请求对象
url=self.request.build\u绝对值\u uri(反向('view\u name',args=(obj.pk,))
)
full_uri.allow_tags=True

每个扩展admin.ModelAdmin的类都有两个可以覆盖的函数:change\u视图和changelist\u视图<编辑单个实例时调用“代码>更改”视图,查看所有项目列表时调用“代码>更改列表”视图

这两个函数充当管理员的视图定义,并包含页面的请求对象。这意味着在这两个函数中,您可以将请求存储为
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
来自django.contrib导入管理
类MyAdmin(admin.ModelAdmin):
列表显示=(
“完整uri”,
)
只读_字段=(
“完整uri”,
)
def change_视图(自身、请求、对象id、表单url=''、额外上下文=None):
#在“更改”视图中访问请求对象
self.request=请求
返回super(MyAdmin,self)。更改视图(请求,对象id,表单url=表单url,额外上下文=额外上下文)
def变更列表视图(自身、请求、额外上下文=无):
#在列表视图中访问请求对象
self.request=请求
返回super(MyAdmin,self).changelist\u视图(请求,额外上下文=额外上下文)
def full_uri(自身、obj):
返回u'{url}'。格式(
#通过两个视图函数设置的self.request访问请求对象
url=self.request.build\u绝对值\u uri(反向('view\u name',args=(obj.pk,))
)
full_uri.allow_tags=True

我想我找到了一种线程安全的方法,在
get\u list\u 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,
    )
def get_list_显示(self,request):
def链接到视图(obj):
返回u'{url}'。格式(
url=request.build\u absolute\u uri(反向('view\u name',args=(obj,))
)
令牌\u访问\u链接。短\u描述=\u('link'))
令牌\u访问\u链接。允许\u标记=真
返回(
链接到视图,
)

我想我找到了一种线程安全的方法,在
get\u list\u 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,
    )
def get_list_显示(self,request):
def链接到视图(obj):
返回u'{url}'。格式(
url=request.build\u absolute\u uri(反向('view\u name',args=(obj,))
)
令牌\u访问\u链接。短\u描述=\u('link'))
令牌\u访问\u链接。允许\u标记=真
返回(
链接到视图,
)

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

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

设置.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

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

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

设置.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

好吧,我想如果我们用
try finally
来围绕这个问题,这样做可能没问题。我不知道为什么您需要在一次尝试中结束对super的调用。我以前从未这样做过。因为ModelAdmin实例由不同的请求使用,所以不建议更改它们的状态。最后是确保不管发生什么情况都能进行清理。对不起。进一步挖掘之后,我不得不接受你的答案,因为它确实不安全。不过我想我找到了一种方法。好吧,我想如果我们用
try finally
来围绕这个问题,那么这样做可能没问题。我不确定你为什么需要在一次尝试中结束对super的调用。我以前从未这样做过。因为ModelAdmin实例由不同的请求使用,所以不建议更改它们的状态。最后是确保不管发生什么情况都能进行清理。对不起。进一步挖掘之后,我不得不接受你的答案,因为它确实不安全。我想我找到了一个方法。。