历史原因,使用django1.6.5,shame on me....
1. 显示admin日志
# 某个app下,建立admin.py 内容如下
from django.contrib.admin.models import LogEntry
class LogEntry_Admin(admin.ModelAdmin):
list_display = ['id', 'user', 'action_time', 'content_type', 'object_id', 'object_repr', 'change_message']
admin.site.register(LogEntry, LogEntry_Admin)
# 有自动注册的库,未使用 https://github.com/Mimino666/django-admin-autoregister
# 之后记录日志如下:
try:
LogEntry.objects.log_action(
user_id=request.user.pk,
content_type_id=ContentType.objects.get_for_model(FooModel).pk,
object_id=None,
object_repr='foo verbose_name',
action_flag=0,
change_message='change foo',
except Exception as e:
logging.error(traceback.format_exc())
2. ModelAdmin 的几个字段的功能
# 列表中需要展示的字段
# 枚举
list_display = ['id', 'name']
# 排除
list_display = [field.name for field in MyModel._meta.fields if field.name != 'foo']
# 列表过滤器
list_filter = ['created', 'updated', 'status']
# 可搜索的字段
search_fields = ['name']
# 动作字段
actions = ['foo', 'bar']
# 只读显示字段, 一般用于添加链接
readonly_fields = ['link']
# 排序字段
ordering = ['-created']
# 查询时同时取出外建对应的model
list_select_related = True
# 列表每页显示多少条
list_per_page = 50
3.添加链接字段
from django.utils.safestring import mark_safe
from django.core.urlresolvers import reverse
class Foo_Admin(admin.ModelAdmin):
list_display = ['id', 'bar_link'] # 列表页中的链接字段
readonly_fields = ['foo_links'] # 编辑页中的链接字段
def bar_link(self, obj):
try:
# model修改页链接, admin:app名称_模型名称_change
link = reverse("admin:barapp_barmodel_change", args=(bar.id,))
return mark_safe('<a href="{}" target="_blank">{}</a>'.format(link, bar.id))
except BarModel.DoesNotExist:
return u'bar不存在'
# 方法名后的short_description是其作为字段的描述
bar_link.short_description = u'bar链接'
def foo_links(self, obj):
try:
links = ''
foos = FooModel.objects.filter(name=obj.name)
for foo in foos:
link = reverse("admin:fooapp_foomodel_change", args=(foo.id,))
linkhtml = mark_safe('<a href="{}" target="_blank">{}</a>'.format(link, foo.id))
links = links + ' ' + linkhtml
return links
except:
return None
foo_links.short_description = u'foo链接'
# 允许html标签
foo_links.allow_tags = True
4.自定义动作
class Foo_Admin(admin.ModelAdmin):
actions = ['my_action']
def my_action(self, request, queryset):
for item in queryset:
PROC(item)
# 把消息显示给用户
self.message_user(request, 'success'
my_action.short_description = 'my wonderful action'
5.扩展动作表单, 添加动作参数
class ExtendedActionsMixin(object):
"""
原始代码及文档地址:https://gist.github.com/rafen/eff7adae38903eee76600cff40b8b659
"""
# actions that can be executed with no items selected on the admin change list.
# The filtered queryset displayed to the user will be used instead
extended_actions = []
def changelist_view(self, request, extra_context=None):
# if a extended action is called and there's no checkbox selected, select one with
# invalid id, to get an empty queryset
if 'action' in request.POST and request.POST['action'] in self.extended_actions:
if not request.POST.getlist(admin.ACTION_CHECKBOX_NAME):
post = request.POST.copy()
post.update({admin.ACTION_CHECKBOX_NAME: 0})
request._set_post(post)
return super(ExtendedActionsMixin, self).changelist_view(request, extra_context)
def get_changelist_instance(self, request):
"""
Returns a simple ChangeList view instance of the current ModelView.
(It's a simple instance since we don't populate the actions and list filter
as expected since those are not used by this class)
"""
list_display = self.get_list_display(request)
list_display_links = self.get_list_display_links(request, list_display)
list_filter = self.get_list_filter(request)
search_fields = self.get_search_fields(request)
list_select_related = self.get_list_select_related(request)
ChangeList = self.get_changelist(request)
return ChangeList(
request, self.model, list_display,
list_display_links, list_filter, self.date_hierarchy,
search_fields, list_select_related, self.list_per_page,
self.list_max_show_all, self.list_editable, self,
)
def get_filtered_queryset(self, request):
"""
Returns a queryset filtered by the URLs parameters
"""
cl = self.get_changelist_instance(request)
return cl.get_queryset(request)
class Custom_ActionForm(ActionForm):
"""自定义admin动作参数表单
参考文档: https://github.com/cundi/blog/issues/32
"""
ARGS_A = 1
ARGS_B = 2
ARGS_C = 3
CHOICES = (
(ARGS_A, u'AAA'),
(ARGS_B, u'BBB'),
(ARGS_C, u'CCC'),
)
# 此处用到的下拉选择字段,可按需使用charfiled
args = forms.ChoiceField(choices=CHOICES, label=u'命令参数')
class Foo_Admin(ExtendedActionsMixin, admin.ModelAdmin):
actions = ['my_action']
action_form = Custom_ActionForm
extended_actions = ['my_action']
def my_action(self, request, queryset):
# args为Custom_ActionForm表单中选择的项
args = int(request.POST.get('args', 0))
if args == Custom_ActionForm.ARGS_A:
PROC(args)
6. 自定义过滤器
from django.contrib import admin
import datetime
from django.contrib.admin import DateFieldListFilter
from django.utils import timezone
class CustomFilter(admin.SimpleListFilter):
"""自定义过滤器"""
parameter_name = 'foo_status' # 作为GET请求url参数
title = u'过滤器名称'
NEW, SUCCESS, FAIL = '0', '1', '2'
def lookups(self, request, model_admin):
return (
(self.NEW, "新建"),
(self.SUCCESS, "成功"),
(self.FAIL, "失败"),
)
def queryset(self, request, queryset):
if not self.value():
return queryset
if self.value() == self.NEW:
return queryset.filter(status=NEW)
if self.value() == self.FAIL:
return
if self.value() == self.SUCCESS:
return
class CustomDateTimeFilter(DateFieldListFilter):
"""扩展admin日期过滤器,支持更多日期
参考: https://stackoverflow.com/questions/37735191/how-do-i-extend-django-admins-datefieldlistfilter-class
"""
def __init__(self, *args, **kwargs):
super(CustomDateTimeFilter, self).__init__(*args, **kwargs)
now = timezone.now()
# When time zone support is enabled, convert "now" to the user's time
# zone so Django's definition of "Today" matches what the user expects.
if timezone.is_aware(now):
now = timezone.localtime(now)
today = now.date()
endyear = now.year
endmonth = now.month
if endmonth == 1:
startmonth = 12
startyear = now.year - 1
else:
startmonth = now.month - 1
startyear = now.year
start = datetime.datetime(startyear, startmonth, 1, 0, 0, 0, 0) # 上月1日0点
end = datetime.datetime(endyear, endmonth, 1, 0, 0, 0, 0) # 本月1日0点
self.links += ((
(u'昨天', {
self.lookup_kwarg_since: str(today - datetime.timedelta(days=1)),
self.lookup_kwarg_until: str(today),
}),
(u'前天', {
self.lookup_kwarg_since: str(today - datetime.timedelta(days=2)),
self.lookup_kwarg_until: str(today - datetime.timedelta(days=1)),
}),
(u'上月', {
self.lookup_kwarg_since: str(start),
self.lookup_kwarg_until: str(end),
}),
))
class Foo_Admin(admin.ModelAdmin):
list_filter = ['status', ('created', CustomDateTimeFilter), CustomFilter]
django-admin-rangefilter # 用于admin中日期范围过滤