我在模型的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)
它返回一个自定义链接(为了简洁,我省略了highlight_link.short_description)更改列表中返回的每条记录。哪个好。但是我想检查当前的查询字符串并根据它更改自定义链接。有没有办法在'highlight_link'中访问Request对象?
答案 0 :(得分: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)
答案 1 :(得分:15)
我这样解决了我的问题。
class MyClassAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(MyClassAdmin, self).queryset(request)
self.request = request
return qs
现在我可以在任何地方使用self.request
<强>更新强>
Changed in Django 1.6: The get_queryset method was previously named queryset.
class MyClassAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyClassAdmin, self).get_queryset(request)
self.request = request
return qs
答案 2 :(得分:3)
没有直接的方法来实现这一目标。我看到了两种可能的解决方案。
将线程本地商店用于同一请求对象
from django.utils._threading_local import locals
globals = locals()
class RadioGridAdmin(admin.ModelAdmin):
def __call__(self, request, *args, **kwargs):
globals['radio_grid_admin_request'] = request
return super(RadioGridAdmin, self).__call__(request, *args, **kwargs)
def highlight_link(self):
request = globals['radio_grid_admin_request']
# request.GET processing
return ('some custom link')
如果您使用简单的非线程Django安装,则可以将请求对象保存为属性:
class RadioGridAdmin(admin.ModelAdmin):
def __call__(self, request, *args, **kwargs):
self.request = request
return super(RadioGridAdmin, self).__call__(request, *args, **kwargs)
def highlight_link(self):
# self.request.GET processing
return ('some custom link')
答案 3 :(得分:2)
小代码澄清 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)
因此,您可以使用self.request
的任何其他方法获取MyClassAdmin
。
如果在self.request
方法中定义get_queryset
(未在__init__
中声明),PyCharm将生成警告Instance attribute attribute_name defined outside __init__
。
答案 4 :(得分:2)
根据@ taha-jahangir的回答添加了线程安全位,描述了如何refactor this into a mixin。这是混音:
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)
使用mixin的子类ModelAdmin:
class PollAdmin(ModelAdminRequestMixin, admin.ModelAdmin):
pass
...你可以从任何方法调用self.get_request()
。
答案 5 :(得分: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)
由于它是全球性的,您现在可以在此处访问它:
def highlight_link(self):
# access start_date here
答案 6 :(得分:0)
import threading
_thread_local = threading.local()
def get_thread_local_request():
return getattr(_thread_local, "request", None)
class RadioGridAdmin(admin.ModelAdmin):
list_display = ('display_field', ...)
def display_field(self, obj):
# ...
request = get_thread_local_request()
# ...
答案 7 :(得分:0)
这是@ user27478 answer的编辑版本,它使用线程局部变量:
class RadioGridAdmin(admin.ModelAdmin):
def __init__(self, model, admin_site):
super().__init__(model, admin_site)
self._request_local = threading.local()
def changelist_view(self, request, extra_context=None):
self._request_local.request = request
return super().changelist_view(request, extra_context)
@property
def _request(self):
return self._request_local.request
def example_highlight_link(self, obj):
changelist = self.get_changelist_instance(self._request)
url = changelist.get_query_string(new_params={'key1': 1})
答案 8 :(得分:0)
from functools import partial, update_wrapper, lru_cache
# Django admin call 2 times get_list_display.
# We need to return the same function to make the method sortable using 'admin_order_field'
# https://github.com/django/django/blob/2161db0792f2e4d3deef3e09cd72f7a08340cafe/django/contrib/admin/templatetags/admin_list.py#L84
@lru_cache(maxsize=100)
def cache_display_wrap(f, request):
wf = partial(f, request)
nf = update_wrapper(wf, f)
return nf
class ModelAdminMixin(admin.ModelAdmin):
def get_list_display(self, request):
def check_needs_request(display):
f = getattr(self, display, None) if not callable(display) else display
if f and getattr(f, 'needs_request', False):
return cache_display_wrap(f, request)
return display
return [check_needs_request(display) for display in super().get_list_display(request)]
from django.contrib import admin
from core.admin_mixins import ModelAdminMixin
@admin.register(AnyModel)
class AnyModelAdmin(ModelAdminMixin, admin.ModelAdminMixin):
list_display = ['id', 'especial_display_with_request']
def especial_display_with_request(self, request, obj):
# Make something special with the request
return obj.any_field
especial_display_with_request.needs_request = True # Similar to short_description or any other django admin attr.
来源:https://gist.github.com/pricco/24826bae3d5102d963eb13ecc0493f33
答案 9 :(得分:-2)
这有什么问题:
def highlight_link(self, request):
# access start_date here