xadmin进阶应用,并替换Django的admin

最近在做一个项目,后台计划用Python实现,采用django+xadmin的组合。网上关于xadmin的教程很零散,官方文档的网址还打不开,略有尴尬,此篇文章是xadmin使用的一些心得。如果需要源码请留言。

软件版本

python 3.7.2
Django 2.1.5
xadmin 2.0.1
PyCharm

首先给大家看下效果图

效果图.jpg

xadmin的安装

常用的安装方式有两种,一种是源码安装,一种是通过pip安装

源码安装方式

从https://github.com/sshwsfc/xadmin 下载xadmin zip文件,然后解压。
在项目app下,比如user下新建文件夹extra_app,将解压后的文件夹xadmin拷贝到extra_app中,然后在文件夹extra_app上点击右键选择'Mark Directory as Sources Root'。

pip 安装方式
pip install git+git://github.com/sshwsfc/xadmin.git@django2

然后在项目的settings.py中添加如下配置

INSTALLED_APPS = [
    .....
    'xadmin',
    'crispy_forms',
    'reversion'
]

假如你是用的MySql数据库,进行如下配置

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '139.107.172.158',
        'PORT': '3306',
    }
}

同时可以把语言改成中文,时区改成上海

LANGUAGE_CODE = 'zh-Hans'

TIME_ZONE = 'Asia/Shanghai'

USE_TZ = False # 如果没有国际化的需求写False,否则数据中插入时间时,有警告。

下一步配置路由,打开项目的urls.py做如下修改

urlpatterns = [
    ......
    path('admin/', xadmin.site.urls),
]

到这一步其实就可以跑起来了
···
python mange.py runserver
···
然后访问http://127.0.0.1:8000/admin/,应该就是登录界面了,这里就不截图了。

个性化定制我们的后台管理系统 和 自定义显示列-第一种情况

下面以user 模块为例
models.py代码如下,直接看注释吧

from django.db import models
import datetime


# 外勤
class User(models.Model):
    name = models.CharField(verbose_name='姓名', max_length=200)
    pwd = models.CharField(verbose_name='密码', max_length=100)
    job_number = models.IntegerField(verbose_name='工号')
    phone = models.CharField(verbose_name='电话号码', max_length=100, null=True, blank=True)

    class Meta:
        # 设置model在后台管理系统中的中文名称
        verbose_name = '外勤信息'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name

    # 自定义显示列,在后台中显示列名为“总诊断量”
    def get_report_all_nums(self):
        return self.report_set.all().count()
    get_report_all_nums.short_description = '总诊断量'

    # 自定义显示列,在后台中显示列名为“月度断量”
    def get_report_month_nums(self):
        year = datetime.datetime.now().year
        month = datetime.datetime.now().month
        first_day = datetime.datetime(year, month, 1)
        today = datetime.datetime.now()
        return self.report_set.filter(report_date__lt=today, report_date__gt=first_day).count()
    get_report_month_nums.short_description = '月度诊断量'

修改user 模块中admin.py如下

import xadmin
from xadmin import views
from msuser import models


class GlobalSetting(object):
    # 后台管理系统的名字
    site_title = '系统后台'
    # 管理系统的设计者,当然你可以改成其他内容
    site_footer = 'Design by XHY'
    # 左侧菜单栏是否可隐藏
    # menu_style = 'accordion'


class UserAdmin(object):
    # 用户管理的图标, 默认是圆圈,丑
    model_icon = 'fa fa-home'
    # 显示的列,对应model相应字段名
    list_display = ['id', 'name', 'pwd', 'job_number', 'phone', 'get_report_month_nums', 'get_report_all_nums']
    # 过滤器,用于查找,这是xadmin的强大之处
    list_filter = ['job_number', 'name', 'phone']
    # 搜索字段
    search_fields = ['job_number', 'name', 'phone']
    # 每页显示的数据行数
    list_per_page = 20
    # 类似

这里还需要补充一点,在菜单栏右侧还需要把菜单组中文化,如下操作

# user 模块下的apps.py
from django.apps import AppConfig


class UserConfig(AppConfig):
    name = 'msuser'
    verbose_name = '用户管理'
# user 模块下的__init__.py
default_app_config = 'msuser.apps.MsuserConfig'

自定义显示列-第二种情况

在实际应用中,我们经常处理一对多的问题,也就是外键。有的时候项目的需求很诡异,举个例子,不仅要用用户的ID作为报告表的外键,同时在报告这个表中还要显示用户的工号,你说这气不气人。如果整个后台时自己写还好解决,但咱们时用的xadmin,经过研究发现,如下方法实现
models.py

from django.db import models
from msuser.models import User


# 报告
class Report(models.Model):
    # 外键
    user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='外勤姓名')
    report_date = models.DateTimeField(verbose_name='诊断时间')
    ......    

    class Meta:
        # 设置model在后台管理系统中的中文名称
        verbose_name = '诊断报告'
        verbose_name_plural = verbose_name

    # 一会在生成json字符串时使用
    def convert_to_dict(self):
        my_dict = {}
        my_dict.update(self.__dict__)
        my_dict.pop("_state")
        my_dict.pop("report_date")
        return my_dict

相应模块的admin.py

import xadmin
from msdiagnosis import models


class ReportAdmin(object):
   model_icon = 'fa fa-home'
   list_display = ['id', 'user', 'get_job_number', 'report_date']
   list_filter = ['report_date', 'user']
   # 这里需要注意的是, 在报告页面,不仅可以根据外键查询,
   # 还可以根据用户的其他列查询,比如姓名,工号
   # 注意书写方式,双下划线 user__name
   search_fields = ['user__id', 'user__name', 'user__job_number']
   list_per_page = 20
   list_display_links = ['id']

   # 自定义显示列, 是用户的工号,在reprot数据库的表中,其实是没有这一列的
   def get_job_number(self, obj):
       return '%s' % obj.user.job_number
   get_job_number.short_description = '外勤工号'


xadmin.site.register(models.Report, ReportAdmin)

python 下的json字符串生成

这里不得不吐槽一下,相比List或对象转json字符串,python的转换过程真的和粑粑一样恶心,最后优化优化在优化,也没有java导几个库,然后直接仍list或对象简单。

我们的需求是这样的,当app请求服务端时,返回如下格式的json。

{
    "code": 0,
    "msg": "成功",
    "data": [
        {
            "id": 2,
            "name": "Cysion",
            "age": 29,
            "pid": "3708261989",
            "gender": 0
        },
        {
            "id": 11,
            "name": "Sophia",
            "age": 22,
            "pid": "3708261998",
            "gender": 1
        },
        {
            "id": 15,
            "name": "lisi",
            "age": 13,
            "pid": "3708262005",
            "gender": 0
        }
    ]
}
python 中对象是不可以直接序列化的,只有其自身对象才可以
对应关系.PNG

下面给大家看个例子,实现上面需求的json

from django.http import JsonResponse, HttpResponse
from .models import Report


# app 获取诊断列表
def get_diagnosis_list(request):
    report_list = Report.objects.filter(user=2)
    # 需求的json格式 {"code": 1, "msg": "获取诊断列表成功", "data": ""}
    
    # 下面的5行就是在为生成json做准备,其实是dict格式, 到return才是生成了真正的json
    res = {"code": 1, "msg": "获取诊断列表成功"}
    r_list = []
    for r in report_list:
        r_list.append(r.convert_to_dict())
    res["data"] = r_list

    return JsonResponse(res, safe=False)

最后生成的json


json.png.jpg

到这里基本就结束了。

你可能感兴趣的:(xadmin进阶应用,并替换Django的admin)