feifeifeisir

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\')

 

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()子主题

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))

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)

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] == \'195\'
    # 关键在这里
    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

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:记录当前登录用户主页面 显示的小组件。

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()

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中

分类:

技术点:

相关文章: