百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

Django+SimpleUI快速开发指南

liebian365 2024-11-22 17:15 13 浏览 0 评论

作者:七号空格
链接:https://zhuanlan.zhihu.com/p/113447102
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

一、环境准备

1、创建新的django项目

2、安装simpleui

# 指定清华源安装simpleui
pip install django-simpleui -i https://pypi.tuna.tsinghua.edu.cn/simple

3、修改django后台模块默认的模板

# 修改project的setting文件,在INSTALLED_APPS 首行引入simple应用
  INSTALLED_APPS = [
      'simpleui',
      'django.contrib.admin',
      'django.contrib.auth',
      'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
      'django.contrib.staticfiles',
      ...
  ]

4、字符集及时区设置

# 修改project的setting文件
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False # 这里务必调整为False,否则时区设置无效

5、静态资源及debug状态设置

# django在开发环境提供bug调试功能,同时该设置影响到runserver运行时的静态资源引入,故生产环境关闭debug开关的时候,保障静态资源的正确引入需要显性定义静态资源
DEBUG = True
# 定义静态资源位置
 STATICFILES_DIRS = [
     os.path.join(BASE_DIR, "static"),
 ]

# or 通过克隆方式将静态资源克隆到项目的静态资源目录,交由ngnix调用
python3 manage.py collectstatic
# 如果克隆报错提示找不到静态目录,请先在settings.py指定静态目录
STATIC_ROOT = os.path.join(BASE_DIR, "static")

# 由于开发过程中simpleui有限通过cdn进行页面渲染,一般情况下我们需要将其调整成本地资源方式,往往生产环境是无法连接外网的
SIMPLEUI_STATIC_OFFLINE = True # 离线模式

6、数据库连接配置

# 这里以postgresql数据库为例,通常建议使用mysql数据库,多数据库连接不在此处讨论
# postgresql
## 安装postgresql驱动
pip install psycopg2-binary
#pip install psycopg2
## 这里需要设置postgresql的schema信息,通过options字典指定配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME' : 'moon',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST':'127.0.0.1',
        'PORT': '5432',
        'OPTIONS': {
                    'options': '-c search_path=myapp'
                },
    }
}

# mysql
## 安装mysql驱动
pip install pymysql
## init文件引入pymysql 用于代理django认可的mysql驱动,同时由于django的版本问题对pymysql的版本存在要求需要增加一个版本欺骗动作
import pymysql
pymysql.version_info = (1, 3, 13, "final", 0)
pymysql.install_as_MySQLdb()
## setting增加mysql连接串配置信息
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'jay_django_test',
        'HOST':'127.0.0.1',
        'USER':'root',
        'PASSWORD':'qweasd',
        'PORT':'3306',
    }
}

7、admin模块进行数据库初始化

# 执行数据库迁移
python manage.py migrate

8、创建admin模块超级管理员角色

python manage.py createsuperuser

9、检查simple是否正确引入

# 浏览器访问 127.0.0.1:8000/admin 使用admin账户登录确认是否生效

二、创建APP

1、创建app

python manage.py startapp myapp
# 将app注册到project
INSTALLED_APPS = [
    'simpleui',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp', # 添加到末尾
]
# 说明:这里注册app是整个app的起点,包括后续涉及到数据迁移文件的生成都依赖于注册列表

2、创建model

# 在app的model创建测试用例的model
import django.utils.timezone as timezone
# Create your models here.
class job_detail(models.Model):
    ## 定义枚举值状态
    JOB_TYPE_STATUS_GP = '01'
    JOB_TYPE_STATUS_DEFAULT = '02'
    JOB_TYPE_STATUS_CHOICES = (
        (JOB_TYPE_STATUS_GP, 'Greenplum函数'),
        (JOB_TYPE_STATUS_DEFAULT, '其他'),
    )

    CREATED_BY = models.CharField('创建人',max_length=32) # 创建人
    CREATED_TIME = models.DateTimeField('创建时间',default=timezone.now) # 创建时间
    UPDATED_BY = models.CharField('更新人',max_length=32) # 更新人
    UPDATED_TIME = models.DateTimeField('更新时间',default=timezone.now)  # 更新时间
    JOB_TYPE = models.CharField('任务类型',max_length=32,
                                choices=JOB_TYPE_STATUS_CHOICES,
                                default=JOB_TYPE_STATUS_DEFAULT
                                ) # 任务类型 01:gp任务;02:datax任务;03:kafka推送任务;04:http请求任务
    JOB_NAME = models.CharField('任务名称',max_length=128) # 任务名称
    JOB_COMMENT = models.CharField('任务描述',max_length=128)  # 任务描述
    IN_PARA = models.CharField('输入参数定义',max_length=32) # 输入参数定义 参数使用英文逗号分隔
    IN_PARA_COMMENT = models.CharField('输入参数描述',max_length=1024)  # 输入参数描述
    OUT_PARA = models.CharField('输出参数定义',max_length=32)  # 输出参数定义 参数使用英文逗号分隔
    OUT_PARA_COMMENT = models.CharField('输出参数描述',max_length=1024)  # 输出参数描述
    VERSION = models.CharField('版本号',max_length=32) # 版本号
    IS_DELETE = models.CharField('是否删除',max_length=1, default='N')  # 逻辑删除 Y:删除;N:正常
    PRO_STATUS = models.CharField('发布状态',max_length=1,default='N') # 发布状态 Y:发布;N:开发

# 生成数据库迁移文件,生产环境建议指定app进行迁移文件生成,避免未完善功能对已有正常版本的影响
python manage.py makemigrations
# 执行数据库迁移
python manage.py migrate

3、配置路由

# 常规的django的web开发一般需要在各个app中创建urls文件,并且将urls路由引入到project的urls中进行统一管理,这里我们通过admin模块的路由注册功能,注册到admin的路由中
# 应用的admin.py中进行model对象注册
from myapp.models import job_detail
admin.site.register(job_detail)

三、页面布局

1、增删改查model测试

# 此时登录到页面上可以发现,刚刚创建的数据表已经作为一个类目在页面上展示了,但同时会发现一个问题,详情页面里面显示的并不是字段信息,而是具体的表名称,此处与我们设想的内容并不匹配。通过这一步骤我们成功验证了app的注册方式。具体展示内容,下面的步骤会详细介绍

2、admin首页布局

# 如上图所示,首页基础展示项目由三个部分组成,往往我们需要对首页进行定制重写,这里我们先把这几个展示模块先关闭
# project的setting文件最后追加如下设置,即可关闭以上几个模块以及信息采集模块
SIMPLEUI_HOME_INFO = False
SIMPLEUI_HOME_QUICK = False
SIMPLEUI_HOME_ACTION = False
SIMPLEUI_ANALYSIS = False
# SIMPLEUI_HOME_TITLE = '百度一下你就知道' # 【首页】按钮文案配置
SIMPLEUI_HOME_PAGE = 'https://www.baidu.com' # 可用于嵌入其他链接,这里可以直接方便的嵌入报表链接
SIMPLEUI_HOME_ICON = 'el el-icon-platform-eleme'
# ICON 支持element-ui和fontawesome  eg:fa fa-user

# 图标ICON 样式查看
https://element.eleme.cn/#/zh-CN/component/icon
http://www.fontawesome.com.cn/cheatsheet/
# 经过实际测试,饿了么的图标稍微有点小,而且数量少

接下来我们一起看下侧边栏设置,simpleui的侧边栏支持菜单排序,动态菜单等功能

# project的setting文件中增加如下配置,icon信息可以参考http://www.fontawesome.com.cn/cheatsheet/
SIMPLEUI_CONFIG = {
    'system_keep': False, # 关闭系统菜单
    'menu_display': ['任务管理', '测试', '权限认证'],
    'dynamic': True,    # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
    'menus': [{
        'app': 'myapp',
        'name': '任务管理',
        'icon': 'fas fa-user-shield',
        'models': [{
            'name': '任务管理1',
            'icon': 'fa fa-user',
            'url': 'job_detail/'
        }]
    },{
        'app': 'auth',
        'name': '权限认证',
        'icon': 'fas fa-user-shield',
        'models': [{
            'name': '用户',
            'icon': 'fa fa-user',
            'url': 'auth/user/'
        }]
    }, {
        'name': '测试',
        'icon': 'fa fa-file',
        'models': [{
            'name': 'Baidu',
            'url': 'http://baidu.com',
            'icon': 'far fa-surprise'
        }, {
            'name': '内网穿透',
            'url': 'https://www.wezoz.com',
            'icon': 'fab fa-github'
        }]
    }]
}

如图所示,新配置的侧边栏已经生效,但点击我们自己创建的app的详情页面提示404错误,从异常信息得知,我们在路由配置上存在问题,系统未能找到我们的路由信息

# 问题配置
'url': 'job_detail/'
# 正确配置
'url': 'myapp/job_detail/'
# 这里大家可以思考下,url的配置与常规的urls.py文件的路由显性引入的异同点

3、页面标题及侧边栏标题定制

# 应用的admin.py文件中
admin.site.site_header = '数据中心'
admin.site.site_title = 'XXX数据中心'
admin.site.index_title = u'XXXX数据中心'

目前看index_title在simpleui中无效,检查过simpleui的template文件确实没使用到这个参数

4、列表查询页面定制

# admin文件中定义展示页面,后续方便页面管理,可以独立文件,通过import方式引入进行注册
from myapp.models import job_detail

@admin.register(job_detail)
class job_detail(admin.ModelAdmin):
    # 设置页面可以展示的字段
    list_display = ('JOB_TYPE', 'JOB_NAME','JOB_COMMENT',
              'IN_PARA','IN_PARA_COMMENT',
              'OUT_PARA','OUT_PARA_COMMENT')
    # 默认不配置的话,第一个字段会存在链接到记录编辑页面
    # list_display_links = None
    list_display_links = ('JOB_NAME',)
    # 设置过滤选项
    list_filter = ('JOB_TYPE', 'CREATED_TIME',)
    # 每页显示条目数 缺省值100
    list_per_page = 1
    # show all页面上的model数目,缺省200
    # list_max_show_all = 200
    # 设置可编辑字段 如果设置了可以编辑字段,页面会自动增加保存按钮
    list_editable = ('IN_PARA_COMMENT',)
    # 按日期月份筛选 该属性一般不用
    # date_hierarchy = 'CREATED_TIME'
    # 按发布日期降序排序
    ordering = ('-CREATED_TIME',)
    # 搜索条件设置
    search_fields = ('JOB_NAME',)

    # 表头字段显示中文名称,这里需要修改models文件,在定义字段的时候增加别名
    # eg1:JOB_NAME = models.CharField('任务名称',max_length=128)
    # eg2: name = models.CharField(max_length=30,verbose_name=u"姓名")

    # 字段关联展示
    ## 场景1、关联其他表的数据展示,此处外键展示不做演示,生产环境尽量减少外键使用

    ## 场景2、枚举信息转义展示
    ###  此处需要在model定义页面通过枚举值转义配置对应展示中文信息,参考model模块代码设置

    """
      这种禁用编辑链接的放法只是不让它在页面中显示,即把超链接去掉了,
      但是还是可以通过手动输入url的方式来进入编辑页面。
      不过可以配合设置fieldsets或者readonly_fieldss来达到目的
      注意:这里建议删除按钮要禁用掉,否则只有拥有view权限的人员依然可以进行删除动作,或者需要进行人员角色判断
    """
    def has_add_permission(self, request):
        # 禁用添加按钮
        return True

    def has_delete_permission(self, request, obj=None):
        # 禁用删除按钮
        return False

5、表单编辑页面配置

"""
这一段主要用于屏蔽 【保存并继续编辑】以及【保存并新建下一个】的按钮,不符合用户习惯
同时需要在 类的定义里面要重写
"""
from django.contrib.admin.templatetags.admin_modify import *
from django.contrib.admin.templatetags.admin_modify import submit_row as original_submit_row

@register.inclusion_tag('admin/submit_line.html', takes_context=True)
def submit_row(context):
    ctx = original_submit_row(context)
    ctx.update({
        'show_save_and_add_another': context.get('show_save_and_add_another', ctx['show_save_and_add_another']),
        'show_save_and_continue': context.get('show_save_and_continue', ctx['show_save_and_continue'])
        })
    return ctx
# --- 分割线 ---  
class job_detail(admin.ModelAdmin):
    ... ...
    # fields 用于控制编辑页面内,需要编辑的字段,逐个显示所有的非AutoField和editable=True
    #        这里可以采用二维元组的方式进行设定对应字段是否在一行显示,可通过 浏览器开发者工具进行查看确认
    # fields = (('JOB_NAME', 'JOB_TYPE'), 'JOB_COMMENT')
    # fieldsets 是二维元组列表,用于对编辑页面的布局,与fields属性互斥
    fieldsets = (
        (None, {
            'fields': ('JOB_NAME', 'JOB_TYPE', 'JOB_COMMENT')
        }),
        ('更多操作', {
            'classes': ('wide', 'extrapretty',),
            'fields': ('IN_PARA', 'OUT_PARA'),
        }),
    )
    save_as_continue = False # 修改完成之后跳转到元素列表页面
    # 重写方法屏蔽按钮
    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['show_save_and_add_another'] = False
        extra_context['show_save_and_continue'] = False
        return super(job_detail, self).change_view(request, object_id,
            form_url, extra_context=extra_context)

6、页面按钮权限配置

# django admin 的权限模块 默认提供了增删改查的权限配置
curr_per_set = {'myapp.view_job_detail','myapp.delete_job_detail','myapp.add_job_detail','myapp.change_job_detail'}
# 而当我们以下图为例:仅仅给某个用户赋权 查询 权限的时候,该用户还存在新增按钮的权限,对已有数据无操作权限,此处启发我们需要去思考页面上面按钮权限如何跟具体角色进行关联
# 当然 django admin 同样支持自定义权限,此处不再讨论
# 这里演示了根据不同用户角色决定是否在页面上显示相应的功能按钮
class job_detail(admin.ModelAdmin):
    ... ...
    def has_add_permission(self, request):
        user_per_set = request.user.get_all_permissions() # 获取当前用户权限
        # 待判断的权限范围
        curr_per_set = {'myapp.view_job_detail','myapp.delete_job_detail','myapp.add_job_detail','myapp.change_job_detail'}
        if 'myapp.add_job_detail' in curr_per_set.intersection(user_per_set):
            return True
        else:
            return False

7、编辑页细致说明

前文中我们已经介绍了简单的编辑页面的排版展示功能,接下来会更加详细地介绍编辑页面的排版,方便大家按照各自功能进行定制化开发

# filesets的样式及描述文案
    fieldsets = (
        (None, {
            'fields': ('JOB_NAME', 'JOB_TYPE', 'JOB_COMMENT')
        }),
        ('更多操作', {
            'classes': ('wide', 'extrapretty',),
            'fields': ('IN_PARA', 'OUT_PARA'),
        }),
    )
# 这里我们通过classes进行fileset的样式定制,常用的主要有 collaspe和wide,collaspe是将fieldset进行折叠,wide主要是增加水平空间,但这两个参数在simpleui中无用处(可能是我们的姿势不对)

# 添加文案说明
fieldsets = (
        (None, {
            'fields': ('JOB_NAME', 'JOB_TYPE', 'JOB_COMMENT')
        }),
        ('更多操作', {
            'classes': ('collaspe',),
            'fields': ('IN_PARA', 'OUT_PARA'),
            'description': '<h1>输入输出参数描述文案</h1>',
        }),
    )
# 这里可以发现 其实我们可以填充html语法,页面同样会直接进行渲染

# 那针对每个单元格的描述应该怎么操作呢?这里我们需要通过对models的help_text的属性添加,一般这个功能用于针对某个具体的字段的使用说明上
IN_PARA = models.CharField('输入参数定义',max_length=32,help_text=u'例如:按照这个样子')
# 多对多选择框 一般用于增加标签等方式上,但需要注意的是这个针对的many-to-many类型字段
## 这里务必要重写__str__方法,否则页面将不会展示具体内容
class job_tags(models.Model):
    title = models.CharField(max_length=30)
    def __str__(self):
        return self.title

class job_detail(models.Model):
    ... ...
    TAG = models.ManyToManyField(job_tags)
## 此时进行数据库迁移操作,系统会同时创建一张关系表

# admin.py中添加
filter_horizontal = ('TAG',)
# 列表页面如何显示 多对多 这种类型的字段,通过自定义函数进行返回详情以及描述
    def tag_list(self):
        return ', '.join([a.title for a in self.TAG.all()])
    tag_list.short_description = '标签'

# admin.py
list_display = ('JOB_TYPE', 'JOB_NAME','JOB_COMMENT',
              'IN_PARA','IN_PARA_COMMENT',
              'OUT_PARA','OUT_PARA_COMMENT','tag_list')
# 只读字段
readonly_fields = ("CREATED_BY",'CREATED_TIME',)
# 自动填充字段 eg:修改某条记录时,自动填充修改人为登录用户
# 时间字段处理,需要在model中指定,例如自动更新时间需要增加 auto_now属性,django使用的时间函数 timezone.now
    CREATED_BY = models.CharField('创建人',max_length=32) # 创建人
    CREATED_TIME = models.DateTimeField('创建时间',default=timezone.now) # 创建时间
    UPDATED_BY = models.CharField('更新人',max_length=32) # 更新人
    UPDATED_TIME = models.DateTimeField('更新时间',auto_now = True)  # 更新时间
# 获取登录人员信息,进行填充,需要重写save_model方法,同时记得设定成只读字段
    def save_model(self, request, obj, form, change):
        if change: # 判断当前是修改状态还是新增状态
            obj.UPDATED_BY = request.user.username
            obj.save()
        else:
            obj.CREATED_BY = request.user.username
            obj.UPDATED_BY = request.user.username
            obj.save()
    readonly_fields = ("CREATED_BY",'CREATED_TIME','UPDATED_BY','UPDATED_TIME',) 
## 这里需要注意的是 获取request人员属性的方法
# 级联修改 一对多关联 一般用于维度表配置展示
## 利用外键,在多的一方,字段指定外键即可,但定义一对多的关系时候需要指定删除方式
new_column = models.ForeignKey('Rela_table', on_delete=models.PROTECT)
## models.CASCADE 此为默认值,级联删除,会删除关联数据
## models.PROTECT 只要存在关联数据就不能删除
## models.DO_NOTHING 什么也不做
### 子表中定义外键
rela_id = models.ForeignKey("job_rela", on_delete=models.DO_NOTHING,default=9999, verbose_name="选择唯一一个父亲")
### 定义依赖的父表
class job_rela(models.Model):
    rela_name = models.CharField('依赖名称',max_length=128) # 任务名称
    rela_id = models.CharField('任务编号', max_length=32)  # 任务名称
    def __str__(self):
        return self.rela_name
### admin中增加显示该字段即可      

# 特殊的一对多,例如:行政区划
parent = models.ForeignKey('self', verbose_name='上级行政区划')
# 只显示当前登录用户自己的数据,超出范围不允许查看
    def get_queryset(self, request):
        qs = super(job_detail, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(CREATED_BY=request.user.username)
# 列表页部分展示字段显示不同颜色
## model中定义字段颜色,通过函数定义
    def colored_name(self):
        if self.PRO_STATUS == 'Y':
            cl_name = 'red'
        else:
            cl_name = 'blue'
        return format_html(
            '<span style="color: {};">{}</span>',
            cl_name,
            self.PRO_STATUS,
        )
    colored_name.short_description = '状态'
## admin中直接引入即可 这里一个大括号代表一个入参

8、集成富文本编辑器实现数据字典展示功能

# 创建数据字典的model信息,包含主表以及字段表,其中主表跟字段表通过主外键进行一对多的关联
class dict_table(models.Model):
    table_name = models.CharField(max_length=64,verbose_name='表名称')
    table_comment = models.CharField(max_length=256,verbose_name='描述')
    table_short_desc = models.CharField(max_length=128,verbose_name='简述')
    create_time = models.DateTimeField(verbose_name='创建时间',default=timezone.now())
    owner = models.CharField(verbose_name='归属人',default='admin',max_length=64)
    update_time = models.DateTimeField(verbose_name='修改时间',auto_now=True)
    description = models.TextField(verbose_name='备注')
    def __str__(self):
        return self.table_name
    class Meta:
        verbose_name = '字典表'
        verbose_name_plural = '字典表'

class dict_columns(models.Model):
    table_id = models.ForeignKey('dict_table',on_delete=models.CASCADE,verbose_name='关联表主键')
    column_name = models.CharField(max_length=128,verbose_name='字段名称')
    column_comment = models.CharField(max_length=128,verbose_name='字段含义及说明')
    def __str__(self):
        return ''
    class Meta:
        verbose_name = '字段详情'
        verbose_name_plural = '字段详情'

# 添加测试记录
# admin文件中创建表名的列表页并且注册到路由中
class dict_columns(admin.TabularInline):
    model = dict_columns
    can_delete = False
    show_change_link = False
    extra = 1
    editable_fields = []
    list_display = ['column_name','column_comment']
    list_display_links = ()
    readonly_fields = ['column_name','column_comment']
    original = False
    def has_add_permission(self, request,obj=None):
        user_per_set = request.user.get_all_permissions() # 获取当前用户权限
        # 待判断的权限范围
        curr_per_set = {'myapp.view_dict_columns','myapp.delete_dict_columns','myapp.add_dict_columns','myapp.change_dict_columns'}
        if 'myapp.add_dict_columns' in curr_per_set.intersection(user_per_set):
            return True
        else:
            return False

@admin.register(dict_table)
class dict_table(admin.ModelAdmin):
    list_display = ('table_name', 'table_short_desc', 'create_time',
                    'owner')
    list_display_links = ('table_name',)
    list_filter = ('table_name',)
    def has_add_permission(self, request,obj=None):
        user_per_set = request.user.get_all_permissions() # 获取当前用户权限
        # 待判断的权限范围
        curr_per_set = {'myapp.view_dict_table','myapp.delete_dict_table','myapp.add_dict_table','myapp.change_dict_table'}
        if 'myapp.add_dict_table' in curr_per_set.intersection(user_per_set):
            return True
        else:
            return False

    def has_delete_permission(self, request, obj=None):
        return False

    save_as_continue = False  # 修改完成之后跳转到元素列表页面

    def change_view(self, request, object_id, form_url='', extra_context=None):
        extra_context = extra_context or {}
        extra_context['show_save_and_add_another'] = False
        extra_context['show_save_and_continue'] = False
        return super(dict_table, self).change_view(request, object_id,
                                                   form_url, extra_context=extra_context)

    fieldsets = (
        ('基本信息', {
            'fields': ('table_name', 'create_time', 'owner','update_time')
        }),
        ('说明', {
            'fields': ('description', )
        }),
    )
    readonly_fields = ("table_name", 'create_time', 'owner', 'update_time',)
    inlines = [dict_columns,]

9、自定义按钮实现导入导出功能

# 出处:参考simpleui官方文档
        # 增加自定义按钮
    actions = ['custom_button']

    def custom_button(self, request, queryset):
        pass

    # 显示的文本,与django admin一致
    custom_button.short_description = '测试按钮'
    # icon,参考element-ui icon与https://fontawesome.com
    custom_button.icon = 'fas fa-audio-description'

    # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
    custom_button.type = 'danger'

    # 给按钮追加自定义的颜色
    custom_button.style = 'color:black;'

    # 链接按钮,设置之后直接访问该链接
    # 3中打开方式
    # action_type 0=当前页内打开,1=新tab打开,2=浏览器tab打开
    # 设置了action_type,不设置url,页面内将报错
    # 设置成链接类型的按钮后,custom_button方法将不会执行。

    custom_button.action_type = 1
    custom_button.action_url = 'http://www.baidu.com'

10、Echart组件引入以及页面个性化调整

# django admin 支持自定义template,大部分情况下我们是需要重新修改 change页面
class RecordAdmin(admin.ModelAdmin):
    change_form_template = 'admin/extras/record_change_form.html'
    ...
# 这个我们定义的页面需要继承 {% extends "admin/change_form.html" %}
# 在urls.py中添加一条对应的url信息以及对应的view函数进行处理渲染

四、应用部署步骤

Step1、安装ngnix

Step2、安装uwsgi

Step3、配置uwsgi

Step4、配置ngnix

Step5、启动服务


至此,我们已经基本上把django+simpleui的快速开发方式介绍了一遍,基本上能够满足一个创业团队或者小型团队的快速工具化的需求。其余基于django使用技巧以及部分源码解读也会在后续其他文章中放出。

相关推荐

C#夯实基础-Lambda在List中的使用

在C#中基本类型比如List,Dictionary,数组等都有委托来实现相关的操作。此时Lambda表达式就可以使用了.实例1,查找字符串List的包含a的元素...

在C#中,如何实现对集合中元素的自定义排序?

在C#中,可以通过多种方式实现对集合中元素的自定义排序,主要包括:...

C++11 新特性面试题_c++ 11 面试题

1、C++11中引入了哪些新的智能指针类型?请描述它们的用法和区别。C++11中引入了三种新的智能指针类型:std::unique_ptr,std::shared_ptr,和std::weak_...

为什么要使用lambda表达式?原来如此,涨知识了

为什么要使用Lambda表达式先看几段Java8以前经常会遇到的代码:创建线程并启动...

[编程基础] Python lambda函数总结

Pythonlambda函数教程展示了如何在Python中创建匿名函数。Python中的匿名函数是使用lambda关键字创建的。...

硬核!Java 程序员必须掌握的 10 个 简化代码的 Lambda 表达式!

大家好,我是一位在架构师道路上狂奔的码农,今天给大家介绍一下程序员必须掌握的10个Lambda表达式,这些表达式几乎涵盖了在实际编程中经常用到的常见场景。相信通过这10个Lambda表...

一文读懂lambda表达式_lambda表达式由来

作者:youngyan,腾讯PCG数据工程工程师...

Java基础知识 - lambda 表达式_javalambda表达式用法

1、表达式语法1)lambda的命名采用的是数学符号λ;...

Python学习笔记 | 匿名函数lambda、映射函数map和过滤函数filter

什么是匿名函数?定义:没有函数名的自定义函数场景:函数体非常简单,使用次数很少,没有必要声明函数,通常搭配高阶函数使用。...

Java Lambda表达式详解(非常全面)

JavaLambda表达式是JDK8引入的,是一个比较重要的特性。@mikechenLambda表达式简介...

Python函数—lambda表达式_python中lambda函数的用法讲解

目录...

了解 Lambda:Python 中的单个表达式函数

Python中的lambda关键字提供了声明小型匿名函数的快捷方式。Lambda函数的行为与使用...

在C#中使用Lambda编写一个排序算法,比较其与传统排序算法的优劣

使用Lambda表达式编写排序算法在C#中,Lambda表达式可以用来简化排序逻辑的编写,尤其是在需要自定义排序规则时非常方便。以下示例展示了如何用Lambda表达式实现排序,并与传统排...

一日一技:python中的匿名函数 lambda用法

匿名函数lambda,语法如下:lambdaarguments:expression...

《回炉重造》——Lambda表达式_回炉重造是贬义词吗

前言Lambda表达式(LambdaExpression),相信大家对Lambda肯定是很熟悉的,毕竟我们数学上经常用到它,即λ。不过,感觉数学中的Lambda和编程语言中的Lamb...

取消回复欢迎 发表评论: