Django Admin:如何访问admin.py中的请求对象,以获取list_display方法?

Eri*_*rik 21 django request django-admin

我在我的模型的admin.py类中添加了一个方法'highlight_link':

class RadioGridAdmin(admin.ModelAdmin):

    list_display = ('start_time', highlight_link)

    def highlight_link(self):
        return ('some custom link')


admin.site.register(RadioGrid, RadioGridAdmin)
Run Code Online (Sandbox Code Playgroud)

它返回一个自定义链接(为了简洁,我省略了highlight_link.short_description)在更改列表中返回的每个记录.哪个好.但是我想检查当前的查询字符串并根据它更改自定义链接.有没有办法在'highlight_link'中访问Request对象?

use*_*478 16

class RadioGridAdmin(admin.ModelAdmin):

    def highlight_link(self, obj):
        return (self.param)

   def changelist_view(self, request, extra_context=None):
        self.param = request.GET['param']
        return super(RadioGridAdmin,self).changelist_view(request, extra_context=extra_context)
Run Code Online (Sandbox Code Playgroud)

  • 这不是线程安全的.本地线程可以解决这个问题. (8认同)
  • 因为RadioGridAdmin实例(self)在请求之间共享. (4认同)
  • @CollinAnderson为什么它不是线程安全的?你能给我解释一下吗?谢谢! (2认同)

Die*_*nte 15

我这样解决了我的问题.

class MyClassAdmin(admin.ModelAdmin):

    def queryset(self, request):
        qs = super(MyClassAdmin, self).queryset(request)
        self.request = request
        return qs
Run Code Online (Sandbox Code Playgroud)

现在我可以self.request在任何地方使用

UPDATE

在Django 1.6中更改:get_queryset方法以前命名为queryset.

class MyClassAdmin(admin.ModelAdmin):

    def get_queryset(self, request):
        qs = super(MyClassAdmin, self).get_queryset(request)
        self.request = request
        return qs
Run Code Online (Sandbox Code Playgroud)

  • 仍然可以在1.9中工作但是`queryset`现在必须用`get_queryset`替换. (2认同)

Mar*_*ain 6

描述了如何将其重构为 mixin,并根据@taha-jahangir 的回答添加了线程安全位。这是混合:

import threading

class ModelAdminRequestMixin(object):
    def __init__(self, *args, **kwargs):
        # let's define this so there's no chance of AttributeErrors
        self._request_local = threading.local()
        self._request_local.request = None
        super(ModelAdminRequestMixin, self).__init__(*args, **kwargs)

    def get_request(self):
        return self._request_local.request

    def set_request(self, request):
        self._request_local.request = request

    def changeform_view(self, request, *args, **kwargs):
        # stash the request
        self.set_request(request)

        # call the parent view method with all the original args
        return super(ModelAdminRequestMixin, self).changeform_view(request, *args, **kwargs)

    def add_view(self, request, *args, **kwargs):
        self.set_request(request)
        return super(ModelAdminRequestMixin, self).add_view(request, *args, **kwargs)

    def change_view(self, request, *args, **kwargs):
        self.set_request(request)
        return super(ModelAdminRequestMixin, self).change_view(request, *args, **kwargs)

    def changelist_view(self, request, *args, **kwargs):
        self.set_request(request)
        return super(ModelAdminRequestMixin, self).changelist_view(request, *args, **kwargs)

    def delete_view(self, request, *args, **kwargs):
        self.set_request(request)
        return super(ModelAdminRequestMixin, self).delete_view(request, *args, **kwargs)

    def history_view(self, request, *args, **kwargs):
        self.set_request(request)
        return super(ModelAdminRequestMixin, self).history_view(request, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

使用 mixin 子类 ModelAdmin:

class PollAdmin(ModelAdminRequestMixin, admin.ModelAdmin):
    pass
Run Code Online (Sandbox Code Playgroud)

...你可以self.get_request()从任何方法调用。


val*_*lex 5

小代码澄清了Diego Puente的答案(python 3.6):

class MyClassAdmin(admin.ModelAdmin):
    def __init__(self, model, admin_site): 
        self.request = None
        super().__init__(model, admin_site)

    def get_queryset(self, request):
        self.request = request      
        return super().get_queryset(request)
Run Code Online (Sandbox Code Playgroud)

所以你可以self.request从任何其他方法获取MyClassAdmin.

self.request如果在方法中定义get_queryset(而不在方法中声明__init__),PyCharm 将生成警告Instance attribute attribute_name defined outside __init__


Eri*_*rik 0

我尝试了这里留下的其他答案,但遇到了对我来说变得越来越复杂的问题。我尝试了一下def __call__()并想出了以下内容。这可能不是正确的方法,但它有效......

在这里获取 GET 变量(全部在 RadioGridAdmin 类中,如我最初的文章中所述):

def __call__(self, request, url):
     global start_date
     start_date = request.GET['param']

     return super(RadioGridAdmin, self).__call__(request, url)
Run Code Online (Sandbox Code Playgroud)

由于它是全球性的,您现在可以在这里访问它:

def highlight_link(self):
    # access start_date here
Run Code Online (Sandbox Code Playgroud)

  • 全局变量在多线程环境中是危险的,例如在 apache 服务器上的 mod_phyton 中运行。 (3认同)