01-下载源码

GitHub地址:https://github.com/sshwsfc/xadmin

# 安装xadmin

由于使用的是Django2.0的版本,所以需要安装xadmin项目django2分支的代码。
在PyCharm里打开命令行工具,输入以下命令完成安装:
pip install git+git://github.com/sshwsfc/xadmin.git@django2 也可以使用https的地址安装,命令如下:
pip install git+https://github.com/sshwsfc/xadmin.git@django2

02-配置settings.py

# 引入下面三个app
INSTALLED_APPS = [
....
'xadmin',
'crispy_forms',
'reversion',
] # 修改使用中文界面
LANGUAGE_CODE = 'zh-Hans' # 修改时区
TIME_ZONE = 'Asia/Shanghai' ALLOWED_HOSTS = ['*', ]

03-配置路由

# urls.py

# -*- coding: utf-8 -*-
# from django.conf.urls import include, url
from django.urls import include, path # Uncomment the next two lines to enable the admin:
import xadmin
xadmin.autodiscover() # version模块自动注册需要版本控制的 Model
from xadmin.plugins import xversion
xversion.register_models() from django.contrib import admin urlpatterns = [
path(r'xadmin/', xadmin.site.urls)
]

04-创建数据库

python manage.py makemigrations

python manage.py migrate

05-创建超级用户

python manage.py createsuperuser

06-拉取静态文件到本地

python manage.py collectstatic

07-站点Model管理

xadmin 可以使用的页面样式控制基本与Django原生的admin一直。

list_display         列表展示的字段

preserve_filters  默认情况下,当你对目标进行创建、编辑或删除操作后,页面会依然保持原来的过滤状态。将preserve_filters设为False后,则会返回未过滤状态。

prepopulated_fields  设置预填充字段。不接收DateTimeField、ForeignKey和ManyToManyField类型的字段。

view_on_site  这个属性可以控制是否在admin页面显示“View site”的链接。这个链接主要用于跳转到你指定的URL页面。

free_query_filter 属性: 默认为 True , 指定是否可以自由搜索. 如果开启自由搜索, 用户可以通过 url 参数来进行特定的搜索,
search_fields 可以通过搜索框搜索的字段名称,xadmin使用的是 模糊查询,存在外键 同 list_filter 一样 注意:只能包括 字符类型,不能有 非字符类型 如:SBBH-20180515-0002
list_filter 可以进行过滤操作的列,例如:存在外键字段class ---》student__class 获取值 ordering 默认排序的字段
readonly_fields 在编辑页面的只读字段
exclude 在编辑页面隐藏的字段
list_editable 在列表页可以快速直接编辑的字段
show_detail_fileds 在列表页显示详情信息
refresh_times 指定列表页的数据定时刷新 例如:refresh_times=(3,5)
list_export 控制列表页导出数据的类型
show_bookmarks 控制是否显示书签功能
data_charts 控制显示图标的样式
model_icon 配置表的图标,可以在 awesome 上下载最新的font-awesome.css 替换,并寻找相应的icon书写
fieldsets ,详细页面时,使用fieldsets标签对数据进行分割显示
empty_value_display = "列数据为空时,显示默认值"
# 列聚合,可用的值:"count","min","max","avg", "sum"
aggregate_fields = {"expire": "max"} # 显示还原按钮,删除修改的信息可以还原
reversion_enable = True # 添加数据时候,一步一步提供数据
wizard_form_list = [
("基础信息", ("name", "contact", "telphone", "address")),
("其它信息", ("customer_id", "expire", "description")),
] fields 表单显示内容, 不包含在内的字段不能编辑
filter_horizontal 从‘多选框’的形式改变为‘过滤器’的方式,水平排列过滤器,必须是一个 ManyToManyField类型,且不能用于 ForeignKey字段,默认地,管理工具使用下拉框 来展现外键 字段 raw_id_fields 将ForeignKey字段从‘下拉框’改变为‘文本框’显示 relfield_style 后台自定义不是下拉选择框,而是搜索框(解决了为什么用户不是下拉框的问题。。) relfield_style = 'fk-ajax'
exclude 在编辑和查看列表时指定不显示的字段
list_editable 列表显示的时候,指定的字段可以直接页面一键编辑
list_display_links 设置默认可编辑字段
list_per_page = 20 每页显示20个
actions = ('ocr_action', 'excel_action', 'auto_excel_action') 在类中自定义的函数方法
auto_excel_action.short_description='自动化导入数据文件' 函数名描述 object_list_template = "test.html" 自定义页面 data_charts 图表,该属性为dict类型,key为图表的标示名称,value为图表的具体设置属性
data_charts = {
"user_count": {'title': u"约运动",
"x-field": "sport_time",
"y-field": ("people_nums",),
},
} 图表属性:   title : 图表的显示名称
  x-field : 图表的 X 轴数据列, 一般是日期, 时间等
  y-field : 图表的 Y 轴数据列, 该项是一个 list, 可以同时设定多个列, 这样多个列的数据会在同一个图表中显示
  order : 排序信息, 如果不写则使用数据列表的排序 # 导出类型
list_export = ('xls', 'xml', 'json') list_export设置为None来禁用数据导出功能
#导出字段
list_export_fields = ('start_people', 'sport', 'sport_time')

# adminx.py

class CashTitleContentAdmin(object):
# 菜单的图标
model_icon = 'fa fa-image'
# 列表显示内容
list_display = ('subtitle', 'content_cash', )
# list_display_links 设置默认可编辑字段
list_display_links = ('subtitle', )
# # 分页显示
# list_per_page = settings.list_per_page
# 过滤器
list_filter = ('content_cash',)
# 表单显示内容
fields = ('subtitle', 'content_cash', )
# 搜索字段
search_fields = ('subtitle', 'content_cash__title', ) xadmin.site.register(cash_title_content, CashTitleContentAdmin)

示例

08-站点的全局配置

# settingx/adminx.py

import xadmin
from xadmin import viewsclass BaseSetting(object):
"""xadmin的基本配置"""
enable_themes = True # 开启主题切换功能
use_bootswatch = True # 支持切换主题 xadmin.site.register(views.BaseAdminView, BaseSetting) class GlobalSettings(object):
"""xadmin的全局配置"""
site_title = "xxx后台管理系统" # 设置站点标题
site_footer = "xxxxxxx" # 设置站点的页脚
menu_style = "accordion" # 设置菜单折叠,在左侧,默认的
# 设置models的全局图标, UserProfile, Sports 为表名
global_search_models = [UserProfile, Sports]
global_models_icon = {
UserProfile: "glyphicon glyphicon-user", Sports: "fa fa-cloud" xadmin.site.register(views.CommAdminView, GlobalSettings)

09-app名称的修改

# app名为users下的apps.py

from django.apps import AppConfig

class UsersConfig(AppConfig):
# 设置app图标
app_icon = 'fa fa-line-chart'
# app名
name = 'users'
verbose_name = u'用户管理' # __init__.py default_app_config='users.apps.UsersConfig'

10-自定义导航菜单顺序

from xadmin import views

class GlobalSetting(object):
def get_site_menu(self):
return (
{'title': '课程管理', 'menus': (
{'title': '课程信息', 'url': self.get_model_url(Course, 'changelist')},
{'title': '章节信息', 'url': self.get_model_url(Lesson, 'changelist')},
{'title': '视频信息', 'url': self.get_model_url(Video, 'changelist')},
{'title': '课程资源', 'url': self.get_model_url(CourseResource, 'changelist')},
{'title': '课程评论', 'url': self.get_model_url(CourseComments, 'changelist')},
)},
{'title': '机构管理', 'menus': (
{'title': '所在城市', 'url': self.get_model_url(CityDict, 'changelist')},
{'title': '机构讲师', 'url': self.get_model_url(Teacher, 'changelist')},
{'title': '机构信息', 'url': self.get_model_url(CourseOrg, 'changelist')},
)},
{'title': '用户管理', 'menus': (
{'title': '用户信息', 'url': self.get_model_url(UserProfile, 'changelist')},
{'title': '用户验证', 'url': self.get_model_url(EmailVerifyRecord, 'changelist')},
{'title': '用户课程', 'url': self.get_model_url(UserCourse, 'changelist')},
{'title': '用户收藏', 'url': self.get_model_url(UserFavorite, 'changelist')},
{'title': '用户消息', 'url': self.get_model_url(UserMessage, 'changelist')},
)},
{'title': '系统管理', 'menus': (
{'title': '用户咨询', 'url': self.get_model_url(UserAsk, 'changelist')},
{'title': '首页轮播', 'url': self.get_model_url(Banner, 'changelist')},
{'title': '用户分组', 'url': self.get_model_url(Group, 'changelist')},
{'title': '用户权限', 'url': self.get_model_url(Permission, 'changelist')},
{'title': '日志记录', 'url': self.get_model_url(Log, 'changelist')},
)}, xadmin.site.register(views.CommAdminView, GlobalSetting)

11-设置只读字段

在使用xadmin的时候,ModelAdmin默认只有对于model的增删改查,但是总是有些字段是不希望用户来编辑的。而 readonly_fields 设置之后不管是admin还是其他用户都会变成只读,而我们通常只是想限制普通用户。 这时我们就可以通过重写 get_readonly_fields 方法来实现对特定用户的只读显示。

class UserInfoAdmin():

    def get_readonly_fields(self, **kwargs):
""" 重新定义此函数,限制普通用户所能修改的字段 """
print(self.org_obj)
if self.user.is_superuser:
self.readonly_fields = []
return self.readonly_fields readonly_fields = ('user_email',)

12-在list_display显示自定义函数:

list_display = ['get_chapter_num']

# 需要在自定义的函数下加上如下内容
def get_chapter_num(self):
return self.chapter_set.all().count()
get_chapter_num.short_description= '章节数'

13-设置页面跳转,需自定义函数

def go_to(self): # 设置列表页跳转
from django.utils.safestring import mark_safe
return mark_safe('<a href="http://www.fishc.com.cn">跳转</a>')
go_to.short_description = '友情链接'

14-如果想添加数据的同时方便添加关联model:inlines 机制 同一个页面 可以添加 所有的相关信息

class ChapterInline:
model = Chapter
extra = 0 在CoursesXadmin 添加 inlines = [ChapterInline]

15-重载显示样式

from xadmin.layout import Main,Fieldset,Row,Side
def get_form_layout(self):
if self.org_obj:
self.form_layout = (
Main(
Fieldset('',
'username', 'password',
css_class='unsort no_title'
),
Fieldset(_('Personal info'),
Row('first_name', 'last_name'), # 显示在一行
'email'
),
Fieldset(_('Permissions'),
'groups', 'user_permissions'
),
Fieldset(_('Important dates'),
'last_login', 'date_joined'
),
),
Side(
Fieldset(_('Status'),
'is_active', 'is_staff', 'is_superuser',
),
) )
return super(UserAdmin, self).get_form_layout()子主题

页面的布局在xadmin/plugins/auth.py里的UserAdmin类,修改这个类里的get_form_layout函数,就可以修改布局

def get_form_layout(self):
if self.org_obj:
self.form_layout = (
#Fieldset表示一个区块
Main(
Fieldset('',
'username', 'password', # 显示字段
css_class='unsort no_title' # css_class='unsort no_title'表示定位区块不能拖动
),
Fieldset(_('Personal info'), #Fieldset第一个参数表示区块名称
Row('first_name', 'last_name'), # Row 表示将里面的字段作为一行显示
'email',
),
Fieldset(_('Permissions'),
'groups', 'user_permissions',
),
Fieldset(_('Important dates'),
'last_login', 'date_joined',
),
),
#Side表示状态区块
Side(
Fieldset(_('Status'),
'is_active', 'is_staff', 'is_superuser',
),
)
)
return super(UserAdmin, self).get_form_layout()

16-model的管理器,一个model 分不同情况 管理

class Course(models.Model):
pass class BannerCourse(Course): # 继承 父类 course
class Meta:
verbose_name = '轮播课程'
verbose_name_plural = verbose_name
proxy = True # 不会生成新的表 # 注册新的表 class CourseSourceAdmin(object):
list_display = ['course', 'name', 'add_time', 'download']
list_filter = ['course', 'name', 'add_time', 'download']
search_fields = ['course', 'name', 'download'] def queryset(self):
qs = super(CourseAdmin, self).queryset() qs = qs.filter(is_banner=False)
return qs

17-获取当前的user表model

from django.contrib.auth import get_user_model  (获取当前的user表model)
User = get_user_model()
site.register(User,Useradmin)

18-卸载注册的model

from django.contrib.auth.models import User

xadmin.site.unregister(User)

19-替换默认的注册 user(继承了abstractuser)

class UserInfoAdmin(object):
list_display = ['auth', 'name', 'depart', 'email', 'username']
list_filter = ['auth', 'name', 'depart', 'email', 'username']
search_fields = ['auth', 'name', 'depart', 'email', 'username']
list_editable = ['auth', 'name', 'depart', 'email', 'username']
list_display_links = ['auth', 'name', 'depart', 'email', 'username']
model_icon = 'fa fa-user-circle-o' from django.contrib.auth import get_user_model # 获取当前的user_model
xadmin.site.unregister(get_user_model()) # 注销 user
xadmin.site.register(UserInfo,UserInfoAdmin) # 注册新的 user

20-表单根据用户显示不同的字段内容  get_model_form

import xadmin
# Register your models here. from .models import User
from xadmin.plugins import auth class UserAdmin(auth.UserAdmin):
list_display = ['id', 'username', 'mobile', 'email', 'date_joined']
readonly_fields = ['last_login', 'date_joined']
search_fields = ('username', 'first_name', 'last_name', 'email', 'mobile')
style_fields = {'user_permissions': 'm2m_transfer', 'groups': 'm2m_transfer'} # 表单根据用户显示不同的字段内容
def get_model_form(self, **kwargs):
if self.org_obj is None:
self.fields = ['username', 'mobile', 'is_staff'] return super().get_model_form(**kwargs) xadmin.site.unregister(User)
xadmin.site.register(User, UserAdmin)

而在 admin 里是 get_fields

# 表单根据用户显示不同的字段内容
def get_fields(self, request, obj=None):

21-模型编辑页面Field分区显示--form_layout

在admin.py中我们可以通过Fieldsets去设置字段的分块显示,例如以下代码:
界面显示会上下分区,分为名字为空和名字为其它的两个区域。

class DeviceAdmin(admin.ModelAdmin):
...
fieldsets = (
(None, {
'fields': ('site', 'device_name', 'device_id', 'device_type', 'account', 'password')
}),
('其它', {
'fields': ('responsible_by', 'device_ip', 'device_model', 'sn_number', 'supplier', 'buy_date', 'expire_date', 'note', 'attachment', 'date'),
}),
)

而在xadmin.py中,这个字段不再生效,需用form_layout去设置。

可分为Main主区域和Side侧边区域,Main或Side中又可通过Fieldset再分多个区域。Fieldset为一个元组,第一个字段为需要设置的名称,其它字段均为模型中的字段名。如下:

class DeviceAdmin(object):
...
form_layout = (
Main(
Fieldset('基础信息',
'site', 'device_name', 'device_id', 'device_type', 'account', 'password'),
Fieldset('EXTRA',
'device_model', 'supplier', 'responsible_by', 'device_ip', 'sn_number'),
),
Side(
Fieldset('其它',
'buy_date', 'expire_date', 'note', 'attachment', 'date'),
)
)

22-获取用户信息并填充模型字段--save_models

有时模型中会需要记录添加数据的用户,保存在created_by这样的字段中。这时我们就需要重写save_model方法,在保存模型时存入用户的信息。

admin.py中会sava_model,如下。

class DeviceAdmin(admin.ModelAdmin):
...
def save_model(self, request, obj, form, change):
obj.area_company = Group.objects.get(user=request.user)
super().save_model(request, obj, form, change)

而xadmin.py中改为使用save_models。

class DeviceAdmin(object):
...
def save_models(self):
   obj = self.new_obj
self.new_obj.area_company = Group.objects.get(user=self.request.user)
super().save_models()

23-根据登录用户或组过滤数据--queryset

需要根据登录用户或组过滤数据时,admin.py中是重写get_queryset方法,xadmin.py中改为重写queryset方法即可。如下:

class DeviceAdmin(object):
...
def queryset(self):
"""函数作用:使当前登录的用户只能看到自己负责的设备"""
qs = super(DeviceAdmin, self).queryset()
if self.request.user.is_superuser:
return qs
return qs.filter(area_company=Group.objects.get(user=self.request.user))
# 用户管理
class UserManageAdmin(object):
list_display = ['id', 'name','addtime','get_UserManage_Taocan' ]
search_fields = ['name']
list_filter = ['phone',]
ordering = ['-id'] # 进入xadmin页面将某个字段倒序排列
readonly_fields = ['addtime'] # 只读字段,不能编辑
# exclude = ['money'] # 不显示的字段
list_editable = ['name', ] # 即使编辑器
relfield_style = 'level' # 带有外键的字段变成搜索格式
model_icon = 'fa fa-user' # 表左边的图标
is_execute = True # 使用js插件 # 禁止页面批量删除
def has_delete_permission(self,*args,**kwargs):
if args:
return True
return False # 自动添加管理员
def save_models(self):
self.new_obj.user = self.request.user
super().save_models() # 设置用户只能查看自己填写的数据
def queryset(self):
qs = super(UserManageAdmin, self).queryset()
if self.request.user.is_superuser: # 超级用户可查看所有数据
return qs
else:
que = qs.filter(user=self.request.user)
return que

24-外键下拉框添加过滤

admin.py中发现将site字段添加到autocomplete_fields(autocomplete_fields作用是下拉选项会多出一个搜索框,方便搜索选择)之后,会自动进行过滤,满足上述场景要求。如果不使用autocomplete_fields,可以通过重写formfield_for_foreignkey方法去做筛选。如下:
class DeviceAdmin(admin.ModelAdmin):
...
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if not self.request.user.is_superuser: # 非superuser进行过滤,superuser可以看到全部
if db_field.name == "site":
kwargs["queryset"] = Site.objects.filter(area_company=Group.objects.get(user=self.request.user))
return super(DeviceAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)

而xadmin.py中没有这个方法了,需要重写formfield_for_dbfield方法。如下:

class DeviceAdmin(object):
...
def formfield_for_dbfield(self, db_field, **kwargs):
if not self.request.user.is_superuser:
if db_field.name == "site":
kwargs["queryset"] = Site.objects.filter(area_company=Group.objects.get(user=self.request.user))
return super(DeviceAdmin, self).formfield_for_dbfield(db_field, **kwargs)

25-后台显示模型类不存在的字段

需求如下:订单信息中显示商品,但是我们知道订单和订单中的商品是分开两个表储存的,通过外键关联起来。那如何在订单信息中显示所包含的商品呢?

一、在订单中再添加一个字段,保存该订单所有商品的简单信息。

二、不修改数据库字段,而是在后台显示时多显示一字段(显示改订单的所有商品的基本信息)

第二种方法的代码如下:自定义一个显示字段(get_goods),该字段必须为只读(readonly_fields)才会显示出来。

class OrdersAdminModel(object):

    def get_goods(self,obj):
goods_queryset = obj.ordergoods_set.all()
return str(["商品%s:%s 单价:%s 元"%(i.goods.id,i.goods.name,i.goods.price) for i in goods_queryset])
get_goods.short_description = '购买的商品' list_display = ['order_id','user','status','get_goods']
readonly_fields = ("order_id",'get_goods')

26-django自带的admin是有save_models和delete_model的,后台修改模型类后就会执行改函数,xadmin中如下

def save_models(self):
# 新的对象
obj = self.new_obj
# 可以在这里面写些逻辑
# 保存该对象
obj.save() def delete_model(self):
# 删除数据对象
obj = self.obj
# 相应的操作
obj.delete()

27-定制HTML模板

add_form_template = None
change_form_template = None
change_list_template = None
delete_confirmation_template = None
delete_selected_confirmation_template = None
object_history_template = None

28-xadmin此版本貌似不能加载views.py

作为破解在 __init__.py中增加了 import views一行,如下:

__init__.py

import views

29-列表视图新增自定义按钮

https://www.cnblogs.com/Tommy-Yu/p/5443127.html

http://www.cnblogs.com/livingintruth/p/3738601.html

30-自定义actions

1. 首先要创建一个 Action 类, 该类需要继承 BaseActionView. BaseActionView 是 ModelAdminView 的子类:

from xadmin.plugins.actions import BaseActionView

class MyAction(BaseActionView):

    # 这里需要填写三个属性
action_name = "my_action" #: 相当于这个 Action 的唯一标示, 尽量用比较针对性的名字
description = _(u'Test selected %(verbose_name_plural)s') #: 描述, 出现在 Action 菜单中, 可以使用 ``%(verbose_name_plural)s`` 代替 Model 的名字. model_perm = 'change' #: 该 Action 所需权限 # 而后实现 do_action 方法
def do_action(self, queryset):
# queryset 是包含了已经选择的数据的 queryset
for obj in queryset:
# obj 的操作
...
# 返回 HttpResponse
return HttpResponse(...)
2. 然后在 Model 的 OptionClass 中使用这个 Action: class MyModelAdmin(object): actions = [MyAction, ]
3. 这样就完成了自己的 Action。

31-给这个方法添加一个boolean的属性并赋值为True,它将显示为on/off的图标

from django.db import models
from django.contrib import admin class Person(models.Model):
first_name = models.CharField(max_length=50)
birthday = models.DateField() def born_in_fifties(self):
return self.birthday.strftime('%Y')[:3] == ''
# 关键在这里
born_in_fifties.boolean = True class PersonAdmin(admin.ModelAdmin):
# 官方文档这里有错,将'name'改为'first_name'
list_display = ('first_name', 'born_in_fifties')

32-屏蔽界面的添加按钮

33-xadmin列表页添加自定义工具栏toolbar

https://blog.csdn.net/iteye_12715/article/details/82678755

34-想对某些字段设置颜色,可用下面的设置

from django.db import models
from django.contrib import admin
from django.utils.html import format_html class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
color_code = models.CharField(max_length=6) def colored_name(self):
return format_html(
'<span style="color: #{};">{} {}</span>',
self.color_code,
self.first_name,
self.last_name,
) class PersonAdmin(admin.ModelAdmin):
list_display = ('first_name', 'last_name', 'colored_name')

35-菜单分组管理

https://www.cnblogs.com/fiona-zhong/p/9647986.html

36-自定义函数作为 列 显示

# models.py

class Course(models.Model):
'
'
'
def get_zj_nums(self):
#获取课程的章节数
return self.lesson_set.all().count()
get_zj_nums.short_description = '章节数' #在后台显示的名称
# adminx.py

class CourseAdmin(object):
list_display = ['get_zj_nums'] # 直接使用函数名作为字段显示

效果如下:

37-增加页面显示的列 ‘跳转’——显示自定义的html代码

# models.py

class Course(models.Model):
.
.
.
def go_to(self):
from django.utils.safestring import mark_safe
#mark_safe后就不会转义
return mark_safe("<a href='https://home.cnblogs.com/u/derek1184405959/'>跳转</a>")
go_to.short_description = "跳转"
# adminx.py

class CourseAdmin(object):
list_display = ['go_to']

效果如下:

38-xadmin主页布局的修改

例如:

数据库是 MySQL,xadmin自带的两张表:xadmin_usersettings、xadmin_userwidget

xadmin_usersettings:字段value的初始值应为 | ,代表将主页面分为两列。

xadmin_userwidget:记录当前登录用户主页面 显示的小组件。

class Dashboard(CommAdminView):

    widget_customiz = True
widgets = []
title = _(u"Dashboard")
icon = None def get_page_id(self):
return self.request.path def get_portal_key(self):
return "dashboard:%s:pos" % self.get_page_id() @filter_hook
def get_widget(self, widget_or_id, data=None):
try:
if isinstance(widget_or_id, UserWidget):
widget = widget_or_id
else:
widget = UserWidget.objects.get(user=self.user, page_id=self.get_page_id(), id=widget_or_id)
wid = widget_manager.get(widget.widget_type) class widget_with_perm(wid): def context(self, context):
super(widget_with_perm, self).context(context)
context.update({'has_change_permission': self.request.user.has_perm('xadmin.change_userwidget')})
wid_instance = widget_with_perm(self, data or widget.get_value())
return wid_instance
except UserWidget.DoesNotExist:
return None @filter_hook
def get_init_widget(self):
portal = []
widgets = self.widgets
for col in widgets:
portal_col = []
for opts in col:
try:
widget = UserWidget(user=self.user, page_id=self.get_page_id(), widget_type=opts['type'])
widget.set_value(opts)
widget.save()
portal_col.append(self.get_widget(widget))
except (PermissionDenied, WidgetDataError):
widget.delete()
continue
portal.append(portal_col) UserSettings(
user=self.user, key="dashboard:%s:pos" % self.get_page_id(),
value='|'.join([','.join([str(w.id) for w in col]) for col in portal])).save() return portal @filter_hook
def get_widgets(self): if self.widget_customiz:
portal_pos = UserSettings.objects.filter(
user=self.user, key=self.get_portal_key())
if len(portal_pos):
portal_pos = portal_pos[0].value
widgets = [] if portal_pos:
user_widgets = dict([(uw.id, uw) for uw in UserWidget.objects.filter(user=self.user, page_id=self.get_page_id())])
for col in portal_pos.split('|'):
ws = []
for wid in col.split(','):
try:
widget = user_widgets.get(int(wid))
if widget:
ws.append(self.get_widget(widget))
except Exception as e:
import logging
logging.error(e, exc_info=True)
widgets.append(ws) return widgets return self.get_init_widget() @filter_hook
def get_title(self):
return self.title @filter_hook
def get_context(self):
new_context = {
'title': self.get_title(),
'icon': self.icon,
'portal_key': self.get_portal_key(),
'columns': [('col-sm-%d' % int(12 / len(self.widgets)), ws) for ws in self.widgets],
'has_add_widget_permission': self.has_model_perm(UserWidget, 'add') and self.widget_customiz,
'add_widget_url': self.get_admin_url('%s_%s_add' % (UserWidget._meta.app_label, UserWidget._meta.model_name)) +
"?user=%s&page_id=%s&_redirect=%s" % (self.user.id, self.get_page_id(), urlquote(self.request.get_full_path()))
}
context = super(Dashboard, self).get_context()
context.update(new_context)
return context @never_cache
def get(self, request, *args, **kwargs):
self.widgets = self.get_widgets()
return self.template_response('xadmin/views/dashboard.html', self.get_context()) @csrf_protect_m
def post(self, request, *args, **kwargs):
if 'id' in request.POST:
widget_id = request.POST['id']
if request.POST.get('_delete', None) != 'on':
widget = self.get_widget(widget_id, request.POST.copy())
widget.save()
else:
try:
widget = UserWidget.objects.get(
user=self.user, page_id=self.get_page_id(), id=widget_id)
widget.delete()
try:
portal_pos = UserSettings.objects.get(user=self.user, key="dashboard:%s:pos" % self.get_page_id())
pos = [[w for w in col.split(',') if w != str(
widget_id)] for col in portal_pos.value.split('|')]
portal_pos.value = '|'.join([','.join(col) for col in pos])
portal_pos.save()
except Exception:
pass
except UserWidget.DoesNotExist:
pass return self.get(request) @filter_hook
def get_media(self):
media = super(Dashboard, self).get_media() + \
self.vendor('xadmin.page.dashboard.js', 'xadmin.page.dashboard.css')
if self.widget_customiz:
media = media + self.vendor('xadmin.plugin.portal.js')
for ws in self.widgets:
for widget in ws:
media = media + widget.media()
return media

xadmin/views/dashboard.py部分源码

39-设置xadmin新用户主页的默认布局

数据库:

# xadmin/model.py

@python_2_unicode_compatible
class UserSettings(models.Model):
user = models.ForeignKey(AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_(u"user"))
key = models.CharField(_('Settings Key'), max_length=256)
value = models.TextField(_('Settings Content')) # 重写save方法
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None): if not self.value:
self.value = "|"
super(UserSettings, self).save()
page_id = 'home'
default_list = [
[{'list': '{"title": "", "model": "auth.user"}'}, ],
[{'list': '{"title": "", "model": "cashflows.bank_cash_flows"}'}, ],
[{'html': '{"title": "Test Widget", "content": "第一次测试!!"}'}, ],
[{'qbutton': '{"title": "aaa"}'}, ],
] for i in default_list:
user_widget = UserWidget()
for j in i:
for z in j.keys():
user_widget.page_id = page_id
user_widget.user_id = self.user_id
user_widget.widget_type = z
user_widget.value = j[z]
user_widget.save() id_list = [] # 存放user的id
a = UserWidget.objects.filter(user_id=self.user)
for i in a:
id_list.append(i.id) self.value = "%s,%s|%s,%s" % (id_list[0], id_list[1], id_list[2], id_list[3]) UserSettings.objects.filter(user_id=self.user).value = self.value
super(UserSettings, self).save()
else:
super(UserSettings, self).save()

40. 根据登录用户user过滤展示数据(list_diaplay)

增加case_username字段,外键User表,新创建的数据与当前登录用户相关联!

# models.py

class case_manage(models.Model):
case_id = models.CharField(max_length=18, verbose_name=u'案件编号')
case_name = models.CharField(max_length=50, verbose_name=u'案件名称')
case_type = models.CharField(max_length=20, verbose_name=u'案件类别', blank=True, null=True)
case_unit = models.CharField(max_length=20, verbose_name=u'办案单位', blank=True, null=True)
case_desc = models.CharField(max_length=255, verbose_name=u'案件描述', blank=True, null=True)
case_people = models.CharField(max_length=20, verbose_name=u'联系人姓名')
case_tel = models.CharField(max_length=20, verbose_name=u'联系人电话', blank=True, null=True)
case_time = models.DateTimeField(verbose_name=u'创建时间', default=timezone.now)
case_username = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='创建人', editable=False, null=True, blank=True) class Meta:
verbose_name = u'案件管理'
verbose_name_plural = verbose_name
db_table = 'case_manage' def operate_btn(self):
# 操作
return mark_safe("<a href='/xadmin/cashflows/lead_case/'>查看账单</a>"
"&nbsp;&nbsp;&nbsp;<a href='/xadmin/cashflows/lead_case/add/'>导入账单</a>")
operate_btn.short_description = "操作"def __unicode__(self):
return self.case_id def __str__(self):
return self.case_id

问题:如果仅允许登录用户查看其自己创建的case_manage数据,该怎么处理?

增加queryset方法:如果是超级用户就可以看全部数据,不是的话,只能显示当前登录用户创建的数据。

    def queryset(self):
qs = super(CaseManageAdmin, self).queryset()
if self.request.user.is_superuser:
return qs
else:
return qs.filter(case_username=self.request.user)
# adminx.py

class CaseManageAdmin(object):
# 列表显示内容
list_display = ['case_id', 'case_name', 'case_desc', 'case_time', 'operate_btn', 'case_username']
# 设置默认可编辑字段
list_display_links = ['case_id', ]
# 过滤器
list_filter = ['case_name', ]
# 表单显示内容
fields = ['case_name', 'case_type', 'case_unit', 'case_desc', 'case_people', 'case_tel', 'case_time', ]
# 搜索字段
search_fields = ['case_name', 'case_type', 'case_unit', 'case_desc', 'case_people', 'case_tel', 'case_time']
# 在编辑页面的只读字段
readonly_fields = ['case_time', ]
actions = ['case_sum', ] def save_models(self):
print(self.user.username)
obj = self.new_obj
if not obj.case_id:
obj.case_id = DBHelper.get_id('case_manage', 'CASE')
if not obj.case_username:
obj.case_username = User.objects.get(username=self.user.username)
obj.save() def queryset(self):
qs = super(CaseManageAdmin, self).queryset()
if self.request.user.is_superuser:
return qs
else:
return qs.filter(case_username=self.request.user) def case_sum(self, request, queryset):
pass
case_sum.short_description = "合并案件"
xadmin.site.register(case_manage, CaseManageAdmin)

adminx.py

增加上述方法后,还需要改变IDCAdmin的注册方式,之前使用的是注解注册方式:

@xadmin.sites.register(case_manage) 

class CaseManageAdmin(object):

这种注册方式,不支持queryset方法,在xadmin系统里,点击“案件管理”菜单,会报错误;

应使用这种方式:xadmin.site.register(case_manage, CaseManageAdmin)

41. admin_order_field支持查询查找以按相关模型上的值排序。此示例在列表显示中包含“作者名字”列,并允许按名字对其进行排序:

https://docs.djangoproject.com/en/1.8/ref/contrib/admin/

42. 获取verbose_name

UserInfo._meta.get_field('name').verbose_name

43. xadmin list_filter 外键显示含有英文,怎么把英文去掉?

# xadmin/plugins/filters.py

# 在这个文件里,第126行
# if len(field_parts) > 1:
# # Add related model name to title
# spec.title = "%s %s" % (field_parts[-2].name, spec.title) # 注释掉!

45. 添加自定义的URL

https://www.cnblogs.com/fangsheng/p/9783245.html

46.xadmin多个model的数据渲染在统一个template中

https://www.cnblogs.com/Tommy-Yu/p/5390555.html

47.admin的空值设置方法

xadmin的使用的更多相关文章

  1. 关于django xadmin的学习改造(菜单名称,更改默认前缀数据库)

    路径xadmin-master\demo_app\app\models.py class c(models.Model): ip_address = models.CharField(max_leng ...

  2. xadmin 自定义视图在uwsgi部署时的一坑

    比如修改登录页的template,代码如下: xadmin.site.register(xadmin.views.LoginView, login_template="card_pool/s ...

  3. django xadmin 外键

    style_fields = {'db栏位名称': "fk-ajax"} 实体关系: Account (*)-->(1) user 表单控件: 下拉框 美化用了selecti ...

  4. django xadmin 插件(3) 列表视图新增自定义按钮

    效果图: 编辑按钮是默认的list_editable属性对应的插件(xadmin.plugins.editable) 放大按钮对应的是自定义插件. 自定义按钮源码: xplugin.py(保证能够直接 ...

  5. django xadmin 插件(2) 列表视图新增一功能列

    以默认的related_link为例(即最后一列). 源码:xadmin.plugins.relate.RelatedMenuPlugin class RelateMenuPlugin(BaseAdm ...

  6. django xadmin 插件(1)

    1. 插件的作用可以是全局的,也可以是只针对某个模型的.通过其 init_request控制是否加载此插件, demo如下: class SCPCardOverviewPlugin(BaseAdmin ...

  7. django xadmin自定义菜单

    1. 自定义菜单 adminx.py class GlobalSetting(object): site_title = u'xxx后台' def kuF_site_menu(self): retur ...

  8. django xadmin多个model的数据渲染在统一个template中

    adminx.py demo class ModelAdmin(object): #.... def get_context(self): context = super(SimCardService ...

  9. django xadmin 模板的定制

    编辑新增等页面对应的modelform为ModelFormAdminView (xadmin.views.edit.ModelFormAdminView) 通过源码分析,新增对象的template属性 ...

  10. Django1.9开发博客(14)- 集成Xadmin

    xadmin是一个django的管理后台实现,使用了更加灵活的架构设计及Bootstrap UI框架, 目的是替换现有的admin,国人开发,有许多新的特性: 兼容 Django Admin 使用 B ...

随机推荐

  1. SQL Server中sp_spaceused统计数据使用的空间总量不正确的原因

    很多时候,我们经常使用sp_spaceused来查看表的空间使用情况,上个月群里有个网友说他使用DELETE删除了数据后,使用sp_spaceused查看,发现该表的分配的空间总量(reserved) ...

  2. c/c++ 类成员变量,成员函数的存储方式,以及this指针在c++中的作用

    c/c++ 类成员变量,成员函数的存储方式,以及this指针在c++中的作用 c++不会像上图那样为每一个对象的成员变量和成员函数开辟内存空间, 而是像下图那样,只为每一个对象的成员变量开辟空间.成员 ...

  3. UICollectionView 基础

    在iOS开发中经常会用到UICollectionView,和UITableView同样即成UIScrollView 但是操作起来比UITableVIew要麻烦一些 ,有些地方需要注意,一下是UICol ...

  4. {windows故障}关于WIN7故障模块StackHash_0a9e解决方法

    问题背景:我给同事重装好系统后,想用驱动精灵(网卡版)给新系统安装驱动,但是在安装驱动精灵的过程中老是出现标题的问题,windows停止工作,导致无法安装,最后看到这两个方法后,把网络适配器禁用,然后 ...

  5. C# -- 二分法查找

    二分法查找:适用于已经排序好的数组 1.二分法查找(入门案例) static void Main(string[] args) { , , , , , , , , , , , , , , , , , ...

  6. 挂载KVM Guest操作系统磁盘

    使用虚拟机时, 发现想要修改虚拟机中的文件非常麻烦, 需要启动虚拟机, 然后再登录进去修改. 对于已经关闭的虚拟机, 为了修改一个文件而启动, 非常耽误时间. 对于一个无法启动的虚拟机(比如启动文件损 ...

  7. Three.js基础学习【修改版】

    一. Three.js官网及使用Three.js必备的三个条件 1.Three.js 官网 https://threejs.org/ 2.使用Three.js必备的三个条件(To actually b ...

  8. 你好,我是梁桐铭,.NET程序员,啰嗦下过去几年来的感悟吧

    序 所有的文章都会有序言,我的当然也不例外. 因为职业和工作的关系,很少有时间陪伴家人,感谢妻子10年以来的容忍和支持,感谢女儿给我生活带来的乐趣. 希望孩子长大了之后能热爱编程(可以不用以它谋生). ...

  9. 在win10 64位系统安装 lxml (Python 3.5)

    本想直接用pip install lxml 命令安装完事,但是由于安装过程中跟VS的一些东西冲突怎么都安装不上,搜索到以下方法,问题解决. 步骤: 1.下载跟python匹配的.whl 文件(lxml ...

  10. Announcing the Updated NGINX and NGINX Plus Plug‑In for New Relic (Version 2)

    In March, 2013 we released the first version of the “nginx web server” plug‑in for New Relic monitor ...