一、安装配置
1.xadmin的安装
下载zip源码
https://github.com/sshwsfc/xadmin/tree/django2
pip install xadmin-django2.zip
2.配置settings
xadmin的Form和页面是基于crispy_forms来实现的
INSTALLED_APPS = [
# 省略
'xadmin',
'crispy_forms',
]
二、配置adminx.py
1.注册后台实体类,将APP下的 admin.py改名为 adminx.py
- 自定义过滤器
from xadmin.layout import Row, Fieldset, Container
from xadmin.filters import RelatedFieldListFilter
import xadmin
# xadmin自定义过滤器:通过字段名的检测动态创建对应的过滤器
class CategoryOwnerFilter(RelatedFieldListFilter):
# 设置当前过滤器需要处理的字段
@classmethod
def test(cls, field, request, params, model, admin_view, field_path):
return field.name == 'category'
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
# 该值默认是查询所有数据,此时进行重新赋值,根据owner进行过滤
self.lookup_choices = Category.objects.filter(owner=request.user).values_list('id', 'name')
- 抽象出的数据处理的基类 base_admin.py
# xadmin中保存数据和查询数据的接口名发生了变化
# 在xadmin中数据都可通过self对象获取到
class BaseOwnerAdmin(object):
"""
1.自动补充文章,分类,标签等编辑页面保存时自动保存owner字段
2.针对queryset过滤当前用户的数据
"""
exclude = ('owner', ) # 设置编辑页中不显示owner字段
# 保存数据到数据库中时自动给owner字段赋值
def save_models(self):
self.new_obj.owner = self.request.user
return super().save_models()
# 设置列表页仅显示当前登陆用户的信息
def get_list_queryset(self):
request = self.request
qs = super().get_list_queryset()
return qs.filter(owner=request.user)
- xadmin后台实体类的注册
from xadmin.filters import manager
# 将过滤器注册到过滤器管理器中,并设置优先权,这样页面加载时会使用我们自定义的过滤器
manager.register(CategoryOwnerFilter, take_priority=True)
# 注册xadmin后台显示的实体类
@xadmin.sites.register(Post)
class PostAdmin(BaseOwnerAdmin):
# 修改编辑页面中form表单元素的样式
form = PostAdminForm
# operator 为自定义的显示字段
list_display = ('title', 'status', 'category', 'owner', 'created_time', 'operator')
# 定义可点击进入编辑页面的字段,不写的话默认为第一个
list_display_links = []
# xadmin自定义过滤器,此处使用字段名,而不是过滤器的类名
list_filter = ['category']
# 定义搜索字段,此处category为外键,双下划线指定关联Category类中的name字段
search_fields = ['title', 'category__name']
# 在对应的字段数据上显示一个详情的接口
show_detail_fields = ['record_time',]
# 提供一个自动刷新的接口:可选择5s或10s刷新
refresh_times = (5, 10)
# 导出模型数据类型,这个默认支持4种导出类型
list_export = ('xls', 'xml', 'json')
# 导出字段
# list_export_fields = ()
# 根据数据绘制图表,显示在列表页上方
data_charts = {
"summary": {
'title': u"余额",
"x-field": "record_time",
"y-field": ("summary", 'balance', 'debt'), # 支持多条数据线
},
}
# 动作相关的配置,是否展示在顶部和底部
actions_on_top = True
actions_on_bottom = True
# 开启顶部的编辑按钮
save_on_top = True
# xadmin关于编辑页的布局设置
form_layout = (
Fieldset('基础信息', 'username', 'password', 'phone'),
Fieldset('个人信息', Row('nickname', 'avatar'), 'sex', 'address',),
Fieldset('权限', 'is_active'),
)
# 编辑页不显示的字段
exclude = ['last_login']
# 设置字段横向或纵向展示
filter_horizontal = ('tag',)
# 定义 自定义显示字段的方法,返回值显示在列表页中
def operator(self, obj):
return format_html(
'<a href="{}">编辑</a>', reverse('xadmin:blog_post_change', args=(obj.id,))
)
# 也可使用xadmin提供的接口
# return format_html(
# '<a href="{}">编辑</a>', self.model_admin_url('change', obj.id)
# )
# 显示自定义显示字段的名称
operator.short_description = '操作'
# xadmin关于静态资源Media的配置,此写法可兼容admin
# @property
# def media(self):
# # xadmin是基于bootstrap的,引入会导致页面样式冲突,此处仅做演示
# media = super().media
# media.add_js(['https://cdn.jsdelivr.net/gh/bootcdn/BootCDN/ajax/libs/bootstrap/4.0.0-beta.2/js/bootstrap.bundle.js'])
# media.add_css({
# 'all': ('http://cdn.bootcss.com/bootstrap/4.0.0-beta.2/css/bootstrap.min.css',),
# })
# return media
- 关于用户类
如果是自定义的User类,配置参照上方
xadmin默认已经注册了自带的User类,如果需要自定义显示则需要先注销,再注册
xadmin.site.unregister(get_user_model())
xadmin.site.register(get_user_model(), UserInfoXAdmin)
- 重写xadmin中数据处理的方法
过滤数据的方法:get_list_queryset
保存数据的方法:save_models
删除数据时触发的方法:delete_models
示例:删除数据时自动删除本地的图片,重写delete_models
@xadmin.sites.register(GoodsType)
class GoodsTypeXAdmin(object):
list_display = ('name', 'image_img', 'count')
search_fields = ("name",)
def count(self, obj):
return GoodsInfo.objects.filter(type=obj).count()
count.short_description = '商品总数'
# xadmin中删除数据时调用的方法,在此处删除本地的图片文件
# 很奇怪,xadmin没有直接调用model中的delete方法
def delete_models(self, queryset):
for item in queryset:
# 去掉路径中开头的/,不然os拼接的时候会有问题
origin_img = item.image.url[1:]
thumbnail_img = item.image.thumbnail.url[1:]
# 这里有个坑,os拼接的时候,第二个路径不能是绝对路径,不然会忽略第一个路径参数
origin_img_path = os.path.join(BASE_DIR, origin_img)
thumbnail_img_path = os.path.join(BASE_DIR, thumbnail_img)
if os.path.exists(origin_img_path):
os.remove(origin_img_path)
if os.path.exists(thumbnail_img_path):
os.remove(thumbnail_img_path)
return super().delete_models(queryset)
三、其余配置
xadmin不支持多站点的配置
xadmin自带log功能,因此不用单独配置
1.配置url
import xadmin
urlpatterns = [
# 省略
url(r'^admin/', xadmin.site.urls, name='xadmin'), # 设置为xadmin站点
]
2.site title和site footer的处理
settings.py中定义系统名称和footer
# 设置xadmin的系统标题和底部展示信息
XADMIN_TITLE = 'BlogType管理后台'
XADMIN_FOOTER_TITLE = 'power by Master-Sun'
3.全局样式配置 (写在某个应用下的adminx.py 中)
# xadmin的全局配置
from xadmin import views
# 开启主题切换,这个弄了之后响应挺慢的
# class BaseSetting(object):
# enable_themes = True
# use_bootswatch = True
#
# xadmin.site.register(views.BaseAdminView, BaseSetting)
# 全局配置
class GlobalSettings(object):
# 修改title
site_title = 'OfferHelp个人自助平台'
# 修改footer
site_footer = 'power by Master-Sun'
# 设置左侧的菜单有下拉菜单的效果
menu_style = 'accordion'
# 设置左侧菜单栏实体类对应的图标
global_search_models = (FinanceRecord,)
# 设置对应的图标,图标参考:https://v3.bootcss.com/components/#glyphicons-glyphs
global_models_icon = {
FinanceRecord: "glyphicon glyphicon-check"
}
# 将全局配置信息进行注册
xadmin.site.register(views.CommAdminView,GlobalSettings)
4.更改app在左侧菜单栏的显示名称
# 修改对应app下的apps.py
from django.apps import AppConfig
class UserConfig(AppConfig):
name = 'user'
verbose_name = '用户管理'
# 在对应app的初始化文件__init__.py中添加如下内容
default_app_config = 'user.apps.UserConfig'
5.新增用户小组件报错
D:\workspace\project_env\OfferHelp-env\Lib\site-packages\xadmin\views\dashboard.py
36行:def render(self, name, value, attrs=None):
改为:36行:def render(self, name, value, attrs=None, renderer=None):
参考:《Django企业开发实战》
https://www.cnblogs.com/lyq-biu/p/9513888.html