stark组件

设计一个快速生成增删改查的框架

django在运行的时候有两个线程,一个是运行项目,一个是检测代码有没有改变。
如果不想让其检测代码是否改变可以使用该命令:
python manage.py runserver 127.0.0.1 8000 —noreload

知识储备

  1. django在项目启动前,先自定义的执行某个文件
    在任意app的 apps文件下的类里定义ready方法就可以实现。
  1. from django.utils.module_loading import autodiscover_modules
  2. class App01Config(AppConfig):
  3. name = 'app01'
  4. def readyself):
  5. autodiscover_modules("start_init")

ready方法可以帮助我们在路由加载前根据app的注册的顺序去所有app的目录下找start_init.py的文件并执行,必须注册了app才会执行该app下的start_init文件

如果在start_init.py执行的时候向某个地方放入了一些值,之后路由加载的时候,可以去这个地方读取值。

2.单例模式
单:一个
例:实例化对象
单例模式:对于一个类永远实例化出一个对象

  1. class Foo(object):
  2. pass
  3. obj1 = Foo()
  4. obj2 = Foo()
  5. 这是实例化了两个对象
  1. 01.py
  2. class Adminsite(object):
  3. pass
  4. site = Adminsite() 这是实例化一个对象
  5. 02.py
  6. import o1
  7. 在导入文件的时候,该文件里的代码就会执行一次,所以就实例化出来site对象
  8. print(01.site)
  9. 此时显示的是引入文件的时候,所实例化出来的对象
  10. import 01
  11. 当再次引入的时候,代码就不会再执行一次了,而是去内存中找原来的值
  12. print01.site
  13. 此时显示的对象和上一次导入的是同一个对象。
  14. 已经导入的文件再次被重新导入的时候,python不会重新解释一遍。而是选择从内存中直接将原来导入的值直接拿过来用。
  15. 多个py文件,同时导入一个文件的时候,都会是使用内存中的值。也就是只被解释一遍,其他文件导入的时候去内存中查找有就拿过来用。

3.django的路由分发 include本质

  1. 正常路由分发配置:
  2. urlpatterns = [ path('txt/',include("app01.urls",namespace='01'))]
  3. 所以include的位置也可以直接放一个元组 (urls模块,app名称,名称空间)
  4. urlpatterns = [ path('txt/',(urls模块,app名称,名称空间))]
  5. include源码如下:
  6. def include(arg, namespace=None):
  7. # arg接受字符串形式的模块路径
  8. app_name = None
  9. # 如果arg是元组的形式进入分支,此时arg并不是元组,而是字符串"app01.urls"
  10. if isinstance(arg, tuple):
  11. # Callable returning a namespace hint.
  12. try:
  13. urlconf_module, app_name = arg
  14. except ValueError:
  15. if namespace:
  16. raise ImproperlyConfigured(
  17. 'Cannot override the namespace for a dynamic module that '
  18. 'provides a namespace.'
  19. )
  20. raise ImproperlyConfigured(
  21. 'Passing a %d-tuple to include() is not supported. Pass a '
  22. '2-tuple containing the list of patterns and app_name, and '
  23. 'provide the namespace argument to include() instead.' % len(arg)
  24. )
  25. #此时的情况要进入此分支:
  26. else:
  27. # 就是 urlconf_module = "app01.urls"
  28. urlconf_module = arg
  29. #判断 urlconf_module 是否是字符串的实例,此处是,将"app01.urls"引入进来并赋值给urlconf_module
  30. if isinstance(urlconf_module, str):
  31. urlconf_module = import_module(urlconf_module)
  32. # 如果 urlconf_module 下有urlpatterns属性则获取并赋值给patterns,没有的话就将urlconf_module赋值给patterns
  33. patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
  34. app_name = getattr(urlconf_module, 'app_name', app_name)
  35. #如果有namespace 没 appname 报错,或者有appname没namespace 报错
  36. if namespace and not app_name:
  37. raise ImproperlyConfigured(
  38. 'Specifying a namespace in include() without providing an app_name '
  39. 'is not supported. Set the app_name attribute in the included '
  40. 'module, or pass a 2-tuple containing the list of patterns and '
  41. 'app_name instead.',
  42. )
  43. # namespace 有值则 namespace = namespace 没值则 namespace = app_name
  44. namespace = namespace or app_name
  45. if isinstance(patterns, (list, tuple)):
  46. for url_pattern in patterns:
  47. pattern = getattr(url_pattern, 'pattern', None)
  48. if isinstance(pattern, LocalePrefixPattern):
  49. raise ImproperlyConfigured(
  50. 'Using i18n_patterns in an included URLconf is not allowed.'
  51. )
  52. #最终return 一个元组 ("app01.urls",appname,namespace)
  53. return (urlconf_module, app_name, namespace)

include本质是返回一个元组(urlconf_module,appname,名称空间)
urlconf_module = import_module(‘app01.urls’) #根据字符串导入模块
本质就是 include里传入的字符串给导入进来
urlconf_module 是 一个urls文件对象,通过此对象可以获取urls.patterns获取分发的路由 也就是urlpatterns列表

根据include本质,所以路由分发应该有3种方式如下:

  1. 方式一:
  2. from django.conf.urls import url,include
  3. urlpatterns = [
  4. url(r'^web/', include("app01.urls")),
  5. ]
  6. 方式二:
  7. include函数主要返回有三个元素的元组。
  8. from django.conf.urls import url,include
  9. from app01 import urls
  10. urlpatterns = [
  11. url(r'^web/', (urls, app_name, namespace)), # 第一个参数是urls文件对象,通过此对象可以获取urls.patterns获取分发的路由列表。
  12. ]
  13. 方式三:
  14. urlpatterns = [
  15. url(r'^web/', ([
  16. url(r'^index/', views.index),
  17. url(r'^home/', views.home),
  18. ], app_name, namespace)), # 既然第一个参数获取的是urlpatterns列表那直接可以将列表写在此处
  19. ]

stark组件 对表做增删改查

分析

  1. 创建django项目
  2. 创建基础业务表
    1. app01/models/用户表&部门表
    2. app02/models/主机表
  3. 对以上的3张表做增删改查
    1. 为每张表创建4个视图函数
      1. 单例模式
    2. 为每张表创建4个url
      1. 路由分发本质
      2. 格式是app名称/表名称/增删改查
      3. app01/userinfo/list
      4. app01/userinfo/add
      5. app01/userinfo/del(\d+)
      6. app01/userinfo/edit(\d+)
      7. 路由器前缀的定制
      8. 路由name的定制
  4. 提取公共的视图函数
    1. xx
  5. 列表页面的显示
    1. 生成表的表头和显示的数据,可以自定义
    2. 不定义表头的时候默认显示的样式
    3. 给显示的字段预留一个方法,可以让不同的权限显示不同的字段
    4. 对于choices字段可以显示中文的实现
    5. 编辑和删除按钮的生成,也应该保留原来的搜索条件
    6. 添加按钮的生成
      1. 用户可以自定义添加按钮是否显示
      2. 预留一个钩子方法 用户可以重新该方法
    7. 分页器的实现:见笔记
  6. 添加页面的显示
    1. 前端页面
      11.stark - 图1
    2. 使用form生成效果,预留钩子,使用户可以使用自定义的form
    3. 在form校验完成后,数据保存前,可以自定义的对某些字段加默认值
    4. 添加完成返回list页面的时候应该使用反向生成url并拿到原来的搜索条件
  7. 编辑页面的显示
    1. 使用model form 实现
    2. 预留钩子,使用户可以使用自定义的form 和 添加是一样的
    3. 在form校验完成后,数据保存前,可以自定义的对某些字段加默认值
    4. 添加完成返回list页面的时候应该使用反向生成url并拿到原来的搜索条件
  8. 删除页面的显示
    1. 删除的实现显示确认删除按钮和取消按钮
    2. 点击删除按钮进行删除,点击取消返回list页面
    3. 删除完成后返回list页面
  9. 其他常用功能
    1. 排序
    2. 模糊搜索 django的Q
      1. 要有一个搜索框 是 form表单,get提交,后台进行筛选 ?search=liu
      2. 后端获取到关键字后,根据定义的列进行查找(多列可以按照 或进行查询)
        11.stark - 图2
      3. 如果根据关键字搜索了,前端需要显示这个值
    3. 批量操作
      1. 在每行数据的前面生成一列check_box
      2. 生成批量删除的按钮
      3. 如按钮和check box 关联起来
      4. 生成的按钮应该是下拉框的样式,因为按钮如果多了就放不下了
        11.stark - 图3
      5. 下拉框的按钮应该是可以自己定制的
      6. 函数名.text = ‘XXX’ 可以给函数加键值,
      7. 函数名.name 可以得到函数名
      8. 使用getattr()
        11.stark - 图4
    4. 组合搜索
      1.数据库的哪些字段要做搜索条件,给展示出来
      1.如果是choices字段要显示choices里的元组的数据展示出来
      3.如果是外键 应该显示的是外键所关联表里的字段
      4.根据字段找到关联的数据给展示出来
      5.用户可以自己定制 哪些数据库字段作为搜索条件,不写有默认值
      6.根据配置的字段,去获取所关联的数据
      7.根据字符串取 models 类中的字段对象。model._meta.get_filesd(“字段名”)
      8.组合搜索的展示

11.stark - 图5


知识储备

数据库对象._meta.get_field(‘数据库字段’).verbose_name #可以拿到该数据库对象中的指定字段对象,该对象可以.verbose_name等操作
数据库对象._meta.app_label #可以获取该对象所在app的app名称 数据库对象也可以换成models表的名称
数据库对象._meta.model_name #可以获取该对象所在modle类的models类名称 数据库对象也可以换成models表的名称
判断一个数据是不是函数:
from types import FunctionType
isinstance(‘sd’,FunctionType)

django在渲染数据的时候让数据显示是安全的
from django.utils.safestring import make_safe

@functools 是干嘛的

函数名传递给前端的时候是会自动加括号执行的接受的是返回值

判断model类的字段是什么类型的:
from django.db.models import ForeignKey
isinstance(字段,ForeignKey)

根据字符串类型的字段名 去models类中获取 字段对象:
modls_class._meta.get_field(“字符串类型的字段名”)

根据字符串类型的字段名 去models类中获取 所关联的表外键 多对多 一对多类型的时候用的:
字段对象.related_model #就可以拿到外键等 所关联的表
得到表后 ,后面跟objects 就可以进行查询等操作了

实例化的对象是不可以被迭代的就是不可以被循环的,如果该类中定义了iter方法,且该方法返回一个迭代器,就称这个类实例化的对象为可迭代对象,该对象是可以被循环的