Day 76 CRM业务——stark组件

stark组件

介绍

stark 组件,是一个帮助开发者快速实现数据库表的增删改查+。

目标

10s 完成一张表的增删改查

前戏

1、django 项目启动时,自定义执行某个 py 文件

django 启动时,且在读取项目中 路由加载 之前执行某个 py 文件

在任意 app 的 apps.py 中的 Config 类中定义 ready 方法,并调用 autodiscover_modules 

from django.apps import AppConfig
from django.utils.module_loading import autodiscover_modules

class App02Config(AppConfig):
    name = 'app02'

    def ready(self):
        autodiscover_modules('xxx')

django 在启动时们就会去已注册的所有 app 的目录下找 xxx.py 并自动导入。

如果发现执行了两次,是因为 django 内部的自动重启导致的:

  使用命令:python manage.py runserver 127.0.0.1:8000 --noreload

  pycharm:Edit Configurations ——> Additional options 输入: --noreload

提示:

  如果 xxx.py 执行的代码向 "某个神奇的地方" 放入了一些值,之后的路由加载时,可以去"某个神奇的地方"读取到原来设置的值

2、单例模式

多例模式

class Foo:
    pass

obj01 = Foo()
obj01.name = 'ysg'
print(obj01)        # <__main__.Foo object at 0x000001D154C76128>

obj02 = Foo()
# print(obj02.name)   # AttributeError: 'Foo' object has no attribute 'name'

print(obj02)        # <__main__.Foo object at 0x000001D154C76278>

 

单例模式

单:一个。

例:实例,对象

如果以后存在一个单例模式的对象,可以现在此对象中放入一个值,然后再在其他的文件中导入该对象,通过对象再次将值获取到。

commons.py

class Foo():
    pass

site = Foo()

app02.py

import commons

print('app02:', commons.site.name)

app01.py

import commons

app01 = commons.site
app01.name = 'ysg'      # <commons.Foo object at 0x0000021DF8C56208>
print(app01)


import commons

app02 = commons.site
print(app02.name)       # ysg
print(app02)            # <commons.Foo object at 0x0000021DF8C56208>

import app02            # <commons.Foo object at 0x0000029587E76198>
                        # app02: ysg

通过 python 模块导入的特性,在 python 中,如果已经导入过的文件再次被重新的导入的时候,python不会在重新解释一遍,而是选择从内存中直接将原来的值拿来用,公用一块内存地址。

 

3、django路由分发的本质:include

方法一:

from django.conf.urls import url, include
from django.contrib import admin


urlpatterns = [
    url(r'^rbac/', include(('rbac.urls', 'rbac'))),
]

 

方法二:

include 函数主要返回有是哪个元素的元组

第一个参数是 urls 文件对象,通过此对象可以获取 urls.patterns 获取分发的路由

from django.urls import path,re_path,include
from django.conf.urls import url

print('this is url')
urlpatterns = [
    url(r'web01/', (urls,app_name,namespace))
]

方法三:

在源码内部,读取路由时:

  如果第一个参数有:urls.patterns 属性,那么子路由就从该属性中获取。

  如果第一个参数无:urls.patterns 属性,那么子路由就是第一个参数。

from django.contrib import admin
from django.urls import path,re_path,include
from django.conf.urls import url
from app02 import views

print('this is url')
urlpatterns = [

    path('admin/', admin.site.urls),
    path('index/', views.index),
    url(r'web01/', ([
                      url(r'^web/', views.index),
                      url(r'^home/', views.login)
                  ], 'appname', 'namespace'))
]

 

stark组件的准备工作

1、创建 django project

 并创建 app01、app02、stark 三个应用

2、创建解除业务表

app01

部门表

class Depart(models.Model):
    '''
    部门表
    '''
    title = models.CharField(verbose_name='部门名称',max_length=32)

 

用户表

class UserInfo(models.Model):
    '''
    用户表
    '''
    name = models.CharField(verbose_name='用户名称',max_length=32)
    age = models.CharField(verbose_name='年龄',max_length=32)
    email = models.CharField(verbose_name='Email',max_length=32)
    depart = models.ForeignKey(verbose_name='部门ID',to=Depart,on_delete=models.CASCADE)

 

app02

class Host(models.Model):
    '''
    主机表
    '''
    host = models.CharField(verbose_name='主机名称',max_length=32)
    ip = models.GenericIPAddressField(verbose_name='IP')

 

数据库迁移

__init__.py

import pymysql
pymysql.install_as_MySQLdb()

 

Terminal 命令行

python manage.py makemigrations
python manage.py migrate

 

stark组件实现

为 app 中的每个 model 类自动创建 URL 以及相关视图函数

url.py

from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from stark.service.v1 import site

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^stark/', site.urls),
]
View Code

 

app01/models.py

from django.db import models

# Create your models here.

class Depart(models.Model):
    '''
    部门表
    '''
    title = models.CharField(verbose_name='部门名称',max_length=32)

class UserInfo(models.Model):
    '''
    用户表
    '''
    name = models.CharField(verbose_name='用户名称',max_length=32)
    age = models.CharField(verbose_name='年龄',max_length=32)
    email = models.CharField(verbose_name='Email',max_length=32)
    depart = models.ForeignKey(verbose_name='部门ID',to=Depart,on_delete=models.CASCADE)
View Code

 

app02/models.py

from django.db import models

# Create your models here.

class Host(models.Model):
    '''
    主机表
    '''
    host = models.CharField(verbose_name='主机名称',max_length=32)
    ip = models.GenericIPAddressField(verbose_name='IP')

class Role(models.Model):
    '''
    角色表
    '''
    title = models.CharField(verbose_name='角色名称',max_length=32)
View Code

 

app01/stark.py

from django.shortcuts import HttpResponse

from stark.service.v1 import site
from app01 import models



class DepartHandler:
    def __init__(self, model_class):
        self.model_class = model_class

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('部门列表界面')

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass


class UserInfoHandler:
    def __init__(self, model_class):
        self.model_class = model_class

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('用户列表界面')

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass


site.register(models.Depart, DepartHandler)
site.register(models.UserInfo, UserInfoHandler)
View Code

 

app02/stark.py

from django.shortcuts import HttpResponse

from stark.service.v1 import site
from app02 import models


class HostHandler:
    def __init__(self, model_class):
        self.model_class = model_class

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('主机列表界面')

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass


site.register(models.Host, HostHandler)


class RoleHandler:
    def __init__(self, model_class):
        self.model_class = model_class

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('角色列表界面')

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        pass


site.register(models.Role, RoleHandler)
View Code

 

v1.py

from django.conf.urls import url


class StarkSite(object):
    def __init__(self):
        self._registry = []
        self.app_name = 'stark'
        self.namespace = 'stark'

    def register(self, model_class, handler_class):
        '''

        :param model_class: model 是数据库表对应的类
        :param handler_class: 处理请求的视图函数所在的类
        :return:
        '''

        self._registry.append({'model_class': model_class, 'handler': handler_class(model_class)})

    def get_urls(self):
        patterns = []
        for item in self._registry:
            model_class = item['model_class']
            handler = item['handler']
            # model_class._meta.app_label 获取数据库表所在的应用名
            # model_class._meta.model_name 获取数据库表的表名称
            # print(model_class._meta.app_label,model_class._meta.model_name)
            app_label, model_name = model_class._meta.app_label, model_class._meta.model_name
            patterns.append(url(r'%s/%s/list/$' % (app_label, model_name), handler.list_view))
            patterns.append(url(r'%s/%s/add/$' % (app_label, model_name), handler.add_view))
            patterns.append(url(r'%s/%s/edit/(?P<pk>\d+)/$' % (app_label, model_name), handler.edit_view))
            patterns.append(url(r'%s/%s/del/(?P<pk>\d+)/$' % (app_label, model_name), handler.del_view))

        return patterns

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace


site = StarkSite()
View Code

 

stark组件开发之提取公共视图函数

# -*- coding: utf-8 -*-

# @File    : v1.py
# @Date    : 2020-06-16
# @Author  : Administrator
from django.conf.urls import url
from django.shortcuts import render, HttpResponse

# stark组件开发之提取公共视图函数
class StarkHandler:
    def __init__(self, model_class):
        self.model_class = model_class

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        data_list = self.model_class.objects.all()
        return render(request,'stark/changelist.html',locals())

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('添加界面')

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('编辑界面')

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('删除界面')


# 为 app 中的每个 model 类自动创建 URL 以及相关视图函数
class StarkSite(object):
    def __init__(self):
        self._registry = []
        self.app_name = 'stark'
        self.namespace = 'stark'

    def register(self, model_class, handler_class=None):
        '''

        :param model_class: model 是数据库表对应的类
        :param handler_class: 处理请求的视图函数所在的类
        :return:
        '''
        if not handler_class:
            handler_class = StarkHandler
        self._registry.append({'model_class': model_class, 'handler': handler_class(model_class)})

    def get_urls(self):
        patterns = []
        for item in self._registry:
            model_class = item['model_class']
            handler = item['handler']
            # model_class._meta.app_label 获取数据库表所在的应用名
            # model_class._meta.model_name 获取数据库表的表名称
            # print(model_class._meta.app_label,model_class._meta.model_name)
            app_label, model_name = model_class._meta.app_label, model_class._meta.model_name
            patterns.append(url(r'%s/%s/list/$' % (app_label, model_name), handler.list_view))
            patterns.append(url(r'%s/%s/add/$' % (app_label, model_name), handler.add_view))
            patterns.append(url(r'%s/%s/edit/(?P<pk>\d+)/$' % (app_label, model_name), handler.edit_view))
            patterns.append(url(r'%s/%s/del/(?P<pk>\d+)/$' % (app_label, model_name), handler.del_view))

        return patterns

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace


site = StarkSite()
View Code

 

stark组件开发之URL分发和默认Handler及别名

app01/stark.py

from django.shortcuts import HttpResponse
from django.conf.urls import url
from stark.service.v1 import site, StarkHandler
from app01 import models


class DepartHandler(StarkHandler):
    def extra_urls(self):
        return [url(r'^update/(?P<pk>\d+)/$', self.update_view)]

    def update_view(self, request, pk):
        return HttpResponse('修改密码')


class UserInfoHandler(StarkHandler):
    pass


site.register(models.Depart, DepartHandler, prev='one')
site.register(models.Depart, DepartHandler)
site.register(models.UserInfo, UserInfoHandler)
View Code

 

v1.py

class StarkHandler:

    # stark组件开发之提取公共视图函数
    def __init__(self, model_class, prev):
        self.model_class = model_class
        self.prev = prev

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        data_list = self.model_class.objects.all()
        return render(request, 'stark/changelist.html', locals())

    def add_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('添加界面')

    def edit_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('编辑界面')

    def del_view(self, request, pk):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        return HttpResponse('删除界面')

    # stark组件开发之URL分发和默认Handler 及别名
    def get_url_name(self, param):
        app_label, model_name = self.model_class._meta.app_label, self.model_class._meta.model_name
        if self.prev:
            return '%s_%s_%s_%s' % (app_label, model_name, self.prev, param)
        return '%s_%s_%s' % (app_label, model_name, param)

    @property
    def get_list_url_name(self):
        '''
        获取列表界面的 url 的 name
        :return:
        '''
        return self.get_url_name('list')

    @property
    def get_add_url_name(self):
        '''
        获取添加界面的 url 的 name
        :return:
        '''
        return self.get_url_name('add')

    @property
    def get_edit_url_name(self):
        '''
        获取编辑界面的 url 的 name
        :return:
        '''
        return self.get_url_name('edit')

    @property
    def get_del_url_name(self):
        '''
        获取删除界面的 url 的 name
        :return:
        '''
        return self.get_url_name('del')

    def get_urls(self):
        '''
        重写 get_urls 可以修改所要生成的 url,和减少 url
        :return:
        '''
        patterns = [
            url(r'^list/$', self.list_view, name=self.get_list_url_name),
            url(r'^add/$', self.add_view, name=self.get_add_url_name),
            url(r'^edit/(?P<pk>\d+)/$', self.edit_view, name=self.get_edit_url_name),
            url(r'^del/(?P<pk>\d+)/$', self.del_view, name=self.get_del_url_name),
        ]
        patterns.extend(self.extra_urls())
        return patterns

    def extra_urls(self):
        '''
        重写 extra_urls 可以增加 url
        :return:
        '''
        return []
View Code

 

 

stark组件开发之列表页面自定义函数扩展

app01/start.py

from stark.service.v1 import site, StarkHandler
from django.utils.safestring import mark_safe
from app01 import models


class DepartHandler(StarkHandler):
    # 自定义页面显示的列(表头和内容)
    def display_edit(self, obj=None, is_header=None):
        if is_header:
            return '编辑'
        return mark_safe('<a href="#">编辑</a>')

    def display_del(self, obj=None, is_header=None):
        if is_header:
            return '删除'
        return mark_safe('<a href="#">删除</a>')

    list_display = ['id', 'title', display_edit, display_del]
View Code

 

v1.py

from django.conf.urls import url
from django.shortcuts import render, HttpResponse
from types import FunctionType


# stark组件开发之提取公共视图函数
class StarkHandler:
    # 定制页面显示的列
    list_display = []

    def __init__(self, model_class, prev):
        self.model_class = model_class
        self.prev = prev

    def get_list_display(self):
        '''
        获取页面上应该显示的列,预留的自定义扩展。如:以后可以根据用户权限的不同显示对应的列
        :return:
        '''
        value = []
        value.extend(self.list_display)
        return value

    def list_view(self, request):
        '''
        部门列表界面
        :param request:
        :return:
        '''
        # 1、处理表格的表头
        # ###### stark 组件开发之列表页面定制列 ######
        # 页面要显示的列
        # 用户访问的表 models.UserInfo  ['name','age','email','depart']
        header_list = []
        list_display = self.get_list_display()
        # 支持 StarkHandler 为空
        if list_display:
            for key_or_fun in list_display:
                if isinstance(key_or_fun, FunctionType):
                    verbose_name = key_or_fun(self, obj=None, is_header=True)
                else:
                    verbose_name = self.model_class._meta.get_field(key_or_fun).verbose_name
                header_list.append(verbose_name)
        else:
            header_list.append(self.model_class._meta.model_name)
        # 处理表的内容
        data_list = self.model_class.objects.all()
        body_list = []
        for row in data_list:
            tr_list = []
            if list_display:
                for key_or_fun in list_display:
                    if isinstance(key_or_fun, FunctionType):
                        tr_list.append(key_or_fun(self, row, is_header=False))
                    else:
                        tr_list.append(getattr(row, key_or_fun))
            else:
                tr_list.append(row)
            body_list.append(tr_list)
        return render(request, 'stark/changelist.html', locals())
View Code

 

posted @ 2020-06-28 13:26  亦双弓  阅读(192)  评论(0编辑  收藏  举报