stark组件

stark组件是根据Django admin为原型写的一个组件,能够让我们告别增删改查.stark组件是可插拔试的组件,

移植性强,而且只用配置文件就能够得到想要的数据

一、stark组件路由分发

admin用这一条路由就实现了注册表单*4的url。

路由分发的原理:

  1. 知识一:admin之路由分发原理:
  2. def text01(request):
  3. return HttpResponse('text01')
  4. def text02(request):
  5. return HttpResponse('text02')
  6. def text03(request):
  7. return HttpResponse('text03')
  8. urlpatterns = [
  9. path('chen/',(
  10. [path('text01/',text01),
  11. path('text02/',text02),
  12. path('text03/',text03),
  13. ],
  14. None,None))
  15. ]
  16. 由一个路由分发出来三个 第一个nonenamespace,第二个是项目名称
  17.  
  18. 一级:
  19. path('chen/',(
  20. [
  21. path()
  22. path()
  23. path()
  24. ],None,None))
  25.  
  26. 由一个路由分发出来三个,第一个路由又可以分发出来两个,二级路由.
  27.  
  28. 第一个nonenamespace,第二个是项目名称
  29.  
  30. 二级:
  31. path('chen/',(
  32. [
  33. path(
  34. [
  35. path(),
  36. path(),
  37. ],None,None))
  38. ]
  39. ,None,None))

路由分发原理

单例模式:

***公共的数据***
一个类只允许实例一个对象
***为了数据统一****

怎么生成单例模式?

方式一:__new__

  1. __new__
  2. class Singleton(object):
  3. _instance = None
  4. def __new__(cls, *args, **kwargs):
  5. # 第一次生成对象的时候走:
  6. if not cls._instance:
  7. cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
  8. # 第二次走的时候直接走这里
  9. return cls._instance
  10. class MyClass(Singleton):
  11. a = 1
  12.  
  13. #那么每次实例对象的时候都是指向 同一个内存地址.
  14. #实例MyClass的时候都是 同一个对象

方式二:python模块

python模块是天然的单例模式:

1.不管模块哪里导入,只要是再次导入都是从.pyc导入,都是一个内存地址
    因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,
   就会直接加载 .pyc 文件,而不会再次执行模块代码。
2.我们只需把模块的对象实例化,每次调用的时候都调用这个对象,就可以获得一个单例对象了。

  1. class StarkSite(object):
  2. """注册model对应的配置类(MondelStark或用户自定制)"""
  3. def __init__(self):
  4. self._registry={}
  5. #self--->site单例对象
  6.  
  7. def register(self,model,stark_class=None):
  8. if not stark_class:
  9. stark_class=MondelStark
  10. self._registry[model] = stark_class(model,self)
  11.  
  12. def get_urls(self):
  13. # self--->site单例对象
  14. temp=[]
  15. for model,stark_class_obj in self._registry.items():
  16. model_name=model._meta.model_name
  17. app_label =model._meta.app_label
  18. temp.append(path('%s/%s/'%(app_label,model_name),stark_class_obj.get_url_dispath))
  19. '''
  20. path('repository/book/'BookStark(book,).get_url_dispath)
  21. path('repository/author/'BookStark(author,).get_url_dispath)
  22.  
  23. '''
  24. return temp
  25.  
  26. @property
  27. def urls(self):
  28. return self.get_urls(),None,None
  29.  
  30. site=StarkSite()

单例

每次调用site就是单例对象

说完单例模式,再说回路由的分发:

stark.site就是一个单例,里面进行注册我们的models

为什么我们要用单例模式???

为了能够把model注册到同一个对象里面,我们就可以实现数据统一调度。

StarkSite形成单例类的代码:

  1. #单例的类
  2. class StarkSite(object):
  3. """注册model对应的配置类(MondelStark或用户自定制)"""
  4. def __init__(self):
  5. self._registry={}
  6. #self--->site单例对象
  7.  
  8. def register(self,model,stark_class=None):
  9. if not stark_class:
  10. stark_class=MondelStark
  11. self._registry[model] = stark_class(model,self)
  12.  
  13. def get_urls(self):
  14. # self--->site单例对象
  15. temp=[]
  16. for model,stark_class_obj in self._registry.items():
  17. model_name=model._meta.model_name
  18. app_label =model._meta.app_label
  19. temp.append(path('%s/%s/'%(app_label,model_name),stark_class_obj.get_url_dispath))
  20. '''
  21. path('repository/book/'BookStark(book,).get_url_dispath)
  22. path('repository/author/'BookStark(author,).get_url_dispath)
  23.  
  24. '''
  25. return temp
  26.  
  27. @property
  28. def urls(self):
  29. return self.get_urls(),None,None

在register()方法里面,我们在注册的前提

大前提!!!!!!!

***思考***

我们里在直接调用这个register方法?

那么里面注册了数据了吗?

答案是没有的,

***思路***

在每次开启项目的时候,能够自动执行某个py文件进行注册

  1. from repository import models
  2. from stark.server.stark import site
  3. from stark.server.stark import MondelStark

引入

  1. #我们需要在stark项目的app里:
  2. from django.apps import AppConfig
  3. from django.utils.module_loading import autodiscover_modules
  4.  
  5. class StarkConfig(AppConfig):
  6. name = 'stark'
  7. def ready(self):
  8. autodiscover_modules('stark',)
  9.  
  10. #每次启动都会执行每个项目的stark.py文件,那么一开启项目就把model注册了.
  11.  
  12. ###########其他项目注册model##########
  13. site.register(models.Book,BookStark)
  14.  
  15. site.register(models.Author,AuthorStark)
  16.  
  17. site.register(models.publish)

自动执行py文件

在其他项目stark.py我们可以自己进行配置类的书写

  1. from stark.server.stark import MondelStark
  2.  
  3. class BookStark(MondelStark):
  4. pass

如何通过模型类获得字符串名称,和该模型所在的app名称:

我们需要构建的是一级分发:

第一个是model所属项目的名称/第二个是model类的类名

(path('%s/%s'%(app_label,model_name),))

  1. for model,class_obj in admin.site._registry.items():
  2.  
  3. print(model._meta.model_name) #打印出该模型的名称
  4.  
  5. print(model._meta.app_label) #打印出该模型的app的名称

二级分发我们需要写在配置类里面:

为什么不能写在单例?

从图中可以看出,如果是单例对象的话,每个model类对应的视图函数都是一样的

我们想要的是每一个model类都需要4个视图函数,

所以我们只能把二级分发放在配置类里面,让每个配置类都生成四个相对应的视图函数

  1. def url_dispath(self):
  2. # self--->stark_class_obj--->每一个单独的配置类.
  3. temp = []
  4. model_name = self.model._meta.model_name
  5. app_label = self.model._meta.app_label
  6. temp.extend([path('add/', self.add_view,name="%s_%s_add"%(app_label,model_name)),
  7. re_path('^(\d+)/delete/', self.delete_view,name="%s_%s_delete"%(app_label,model_name)),
  8. re_path('^(\d+)/change/', self.change_view,name="%s_%s_change"%(app_label,model_name)),
  9. path('', self.show_list,name="%s_%s_list"%(app_label,model_name))])
  10. return temp
  11.  
  12. #起别名,目的是为了反向查询的时候能够查到相对应的url

二级分发

构建表结构:

自定制表头:

配置类继承了MondelStark的配置类

  1. class BookStark(MondelStark):
  2.  
  3. list_display=['id','name','price']
  4.  
  5. site.register(models.Book,BookStark)

构建表格

构建表头知识补充:

#如果客户自定制了配置list_display 那么实例化的时候就先在用户自定义的类里面找
#有则返回给后端......没有再去他的父类里面找list_display为空.

属性的反射

属性和方法都可以进行反射

  1. ###################
  2. 反射:
  3. class B(object):
  4. def__init__(self,name):
  5. self.name=name
  6. chen=B('chenxuming')
  7. s='name'
  8.  
  9. ret=getattr(chen,s)
  10. print(ret) ---->'chenxuming'

属性的反射

如何将表头换成中文:

val = self.config.model._meta.get_field(field).verbose_name
header_list.append(val)

  1. class Book(models.Model):
  2. name = models.CharField(max_length=64,verbose_name='书名')
  3. price= models.IntegerField()
  4.  
  5. name=Book._meta.get_field('name')
  6. #name拿到的是title字段的对象
  7. print(name)
  8. print(type(name))
  9. #可以取里面的属性
  10. name.max_length --->64
  11. name.verbose_name--->'书名'

#判断是否是函数的字段
if callable():

from django.utils.safestring import mark_safe
mark_safe(安全调用标签)

构建表格的代码

  1. def new_list_display(self):
  2. ''''构建初始化列表的字段''
  3. temp=[]
  4. temp.append(MondelStark.checkbox)
  5. temp.extend(self.list_display)
  6. temp.append(MondelStark.get_delete_msg)
  7. if not self.list_display_links:
  8. temp.append(MondelStark.get_edit_msg)
  9. return temp
  10.  
  11. def get_headers(self):
  12. # 构建表头: self.new_list_display=[checkbox,'name','price',delete,edit]
  13. header_list = []
  14. for field in self.config.new_list_display:
  15. if callable(field):
  16. val = field(self.config, header=True)
  17. header_list.append(val)
  18. else:
  19. if field == '__str__':
  20. val = self.config.model_name.upper()
  21. header_list.append(val)
  22. else:
  23. val = self.config.model._meta.get_field(field).verbose_name
  24. header_list.append(val)
  25. return header_list
  26.  
  27. def get_body(self):
  28. # 表数据的创建
  29. new_list = []
  30. for obj in self.data_list:
  31. item_list = []
  32. for item in self.config.new_list_display:
  33. if callable(item):
  34. val = item(self.config, obj)
  35. else:
  36. val = getattr(obj, item)
  37. if item in self.config.list_display_links:
  38. val = mark_safe('<a href="%s">%s</a>' % ( self.config.get_edit_url(obj), val))
  39. item_list.append(val)
  40. new_list.append(item_list)
  41. return new_list
  42.  
  43. [[数据],[数据],[数据]]
  44.  
  45. ##########表头,部分表数据的函数#########
  46.  
  47. def checkbox(self,obj=None,header=False):
  48. if header:
  49. return mark_safe('<input id="choice_all" type="checkbox">')
  50.  
  51. return mark_safe('<input class="item" type="checkbox" name="selected_id" value="%s">'%obj.id)
  52.  
  53. def get_edit_msg(self,obj=None,header=False):
  54. if header:
  55. return "操作"
  56.  
  57. _url=self.get_edit_url(obj)
  58. return mark_safe('<a href="%s">编辑</a>' % _url)
  59.  
  60. def get_delete_msg(self,obj=None,header=False):
  61. if header:
  62. return "操作"
  63. _url=self.get_delete_url(obj)
  64. return mark_safe('<a href="%s">删除</a>'%_url)

构建表格

增:

增和改都是基于ModelForm来实现的。

如果用户自定制

  1. Stark_Model_Form=自定制modelform的类名
  1. class BookStark(MondelStark):
  2. list_display=['id','name','price']
  3. Stark_Model_Form=ModelFormBook
  4. list_display_links = ['name']
  5.  
  6. class ModelFormBook(ModelForm):
  7. """自定制ModelForm类"""
  8. class Meta:
  9. model=models.Book
  10. fields='__all__'
  11.  
  12. labels={
  13. 'name':'书名',
  14. 'price':'价格',
  15. 'pub':'出版社',
  16. 'author':'作者',
  17. }
  18.  
  19. def get_model_class(self):
  20. '''判断是否自定制了ModelForm'''
  21. if not self.Stark_Model_Form:
  22. from django.forms import ModelForm
  23. class ModelDeMo(ModelForm):
  24. class Meta:
  25. model = self.model
  26. fields = '__all__'
  27. return ModelDeMo
  28. else:
  29. return self.Stark_Model_Form
  30.  
  31. def add_view(self,request):
  32. '''增加的视图函数'''
  33. # self--->stark_class_obj--->每一个单独的配置类.
  34. ModelDeMo=self.get_model_class()
  35. if request.method=='GET':
  36.  
  37. form =ModelDeMo()
  38. return render(request, 'oprate/add.html', {'form':form})
  39.  
  40. if request.method=='POST':
  41. form = ModelDeMo(request.POST)
  42. if form.is_valid():
  43. form.save()
  44. return redirect(self.get_list_url())
  45. else:
  46. return render(request,'oprate/add.html',{'form':form})
  47.  
  48. ###########前端#########
  49. <form class="form-horizontal col-sm-7" method="post" novalidate>
  50. {% csrf_token %}
  51. {% for data in form %}
  52. <label>{{ data.label }}</label>
  53. {{ data }}
  54. <div class="errors-form">{{ data.errors.0 }}</div>
  55. {% endfor %}
  56.  
  57. <button type="submit" class="btn btn-success">提交</button>
  58. </form>

add

改:

和增加差不多

  1. def change_view(self,request,nid):
  2. '''改 视图函数'''
  3. # self--->stark_class_obj--->每一个单独的配置类.
  4. ModelDeMo=self.get_model_class()
  5. change_obj=self.model.objects.filter(id=nid).first()
  6. if request.method=='GET':
  7. form=ModelDeMo(instance=change_obj)
  8. return render(request,'oprate/edit.html',{'form':form})
  9.  
  10. if request.method=='POST':
  11. show_url = self.get_list_url()
  12. #instance=change_obj
  13. # form.save()
  14. #执行的是update操作
  15. form=ModelDeMo(data=request.POST,instance=change_obj)
  16. if form.is_valid():
  17. form.save()
  18. return redirect(show_url)
  19. else:
  20. return render(request, 'oprate/edit.html', {'form': form})
  21.  
  22. ###前端###
  23.  
  24. <form class="form-horizontal col-sm-7" method="post" novalidate>
  25. {% csrf_token %}
  26. {% for data in form %}
  27. <label>{{ data.label }}</label>
  28. {{ data }}
  29. <div class="errors-form">{{ data.errors.0 }}</div>
  30. {% endfor %}
  31.  
  32. <button type="submit" class="btn btn-success">提交</button>
  33. </form>

change

删:

删要注意的是需要跳转到一个页面,确保用户误点

  1. def delete_view(self,request,nid):
  2. # 删除视图函数
  3. # self--->stark_class_obj--->每一个单独的配置类.
  4. del_obj = self.model.objects.filter(id=nid).first()
  5. show_url = self.get_list_url()
  6.  
  7. if request.method=='GET':
  8.  
  9. return render(request,'oprate/delete.html',{'show_url':show_url})
  10. if request.method=='POST':
  11. if del_obj:
  12. del_obj.delete()
  13. return redirect(show_url)
  14.  
  15. ###前端######
  16.  
  17. <!DOCTYPE html>
  18. <html lang="en">
  19. <head>
  20. <meta charset="UTF-8">
  21. <title>Title</title>
  22. </head>
  23. <body>
  24. <h1>删除页面</h1>
  25. <form action="" method="post" novalidate>
  26. {% csrf_token %}
  27. <input type="submit" value="确认删除">
  28. <a href="{{ show_url }}">取消</a>
  29. </form>
  30.  
  31. </body>
  32. </html>

search

用户能够自己配置进行模糊查询

Q方法的补充

  1. from django.db.models import Q
  2.  
  3. Q的两种玩法:
  4.  
  5. 第一种:
  6. 查询字段必须是字段
  7. Book.objects.filter(Q(title='yuan')|Q(price=123))
  8.  
  9. 第二种
  10. 查询字段可以是字符串:
  11.  
  12. #实例化一个Q对象
  13. search_connction=Q()
  14. #或查询默认是and
  15. search_connction.connector='or'
  16.  
  17. for search_fiile in self.search_fiile #self.search_fiile 用户自定制的['name','price']
  18. #append里面是一个元组
  19. #search_connction.children.append((search_fiile,'查询的内容'))
  20. search_connction.children.append((search_fiile+'__contains','查询的内容'))模糊查询
  21.  
  22. data_list = self.model.objects.filter(search_list)

Q两种方法

stark实现search

需要自定制字段:

  1. search_fields = ['name']
  1. def get_search_connection(self,request):
  2. '''获取模糊查询的Q'''
  3. self.key_word=request.GET.get('q','')
  4. search_connction=Q()
  5. if self.key_word:
  6. search_connction.connector='or'
  7. for fields in self.search_fields:
  8. search_connction.children.append((fields+'__icontains',self.key_word))
  9. return search_connction
  10.  
  11. search_list=self.get_search_connection(request)
  12.  
  13. data_list = self.model.objects.filter(search_list)
  14.  
  15. ##前端##
  16. {% if showlist.config.search_fields %}
  17. <form action="" method="get" class="pull-right">
  18. <input type="text" name="q" value="{{ showlist.config.key_word }}"><button>查询</button>
  19. </form>
  20. {% endif %}

Django之stark组件1的更多相关文章

  1. 【django之stark组件】

    一.需求 仿照django的admin,开发自己的stark组件.实现类似数据库客户端的功能,对数据进行增删改查. 二.实现 1.在settings配置中分别注册这三个app # Applicatio ...

  2. django 之 stark组件

    ----------------------------------------------------------------烦恼没完没了,内心动荡不安,呜呼哀哉. 一.有个特殊的需求,需要用sta ...

  3. Django之stark组件

    现在让我说啥是stark组件,我也说不清楚.反正从今天讲的知识来看,今天完成的就是自己写一个模块,这个模块包含了admin后台管理工具的一些比较好用的功能,我们把它提炼出来,也就是相当于自己写一个ad ...

  4. Django之stark组件的使用和总结

    Stark组件的使用 组件的字段 list_display=[] 需要显示的字段 list_display_links=[] #需要链接编辑字段 Stark_Model_Form=[] #设置Mode ...

  5. Django之stark组件2

    action批量处理功能 用户可以自定义批量处理功能,但是默认的有批量删除功能. ***思路*** 1,定义一个列表用来装action的类名并extend用户自定义列表 2.循环该列表获取到函数名(用 ...

  6. stark组件之pop操作【模仿Django的admin】

    一.先看下什么django的admin的pop到底是个什么东西 其实就是这么一个东西, a.在添加页面,在一对多和多对多的项后加了一个+号 b.点击这个加号,会弹出对应的添加 页面,在新的添加 c.添 ...

  7. stark组件之批量操作【模仿Django的admin】

    一.先看下django的admin是如何实现批量操作 首先在配置类中定义一个函数 然后我们为这个函数对象设置一个属性,这个属性主要用来显示在select标签中显示的文本内容 最后把函数对象放到一个ac ...

  8. stark组件之搜索【模仿Django的admin】

    一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...

  9. stark组件之路由分发【模仿Django的admin】

    一.先看下django的admin是如何进行路由分发的 1.先看下django的admin的url路径有哪些 其实很简单,假如有一个书籍表,那么每张表对应四个url,增.删.改.查 查看的url ht ...

随机推荐

  1. 模拟服务器MockServer之Moco详细介绍

    转载:http://blog.csdn.net/vite_s/article/details/54583243 前面一篇介绍了如何用mockito来测试我们的一些异步任务,例如网络请求时候的异步回调. ...

  2. Oracle基础(一) Oracle的安装和卸载

    一.数据库的基本概念. 数据库就是数据存储的仓库,可以更快的查询.处理.统计数据,还可以保持数据的一致性.共享性和安全性,方便只能的分析,产生新的有用的信息. 1.数据库的发展阶段: (1)萌芽阶段: ...

  3. 怎样取消Macbook上顽固的开机启动项

    博主遇到的一个顽固启动项是Cisco Anyconnect.我仅仅是偶尔须要使用VPN.可是安装了Cisco Anyconnect之后,每次开机它都会启动,非常烦人. 1 通过系统设置 首先,博主希望 ...

  4. lodash 数组裁剪 drop

    _.drop(array, [n=1]) 裁剪数组中的前 N 个数组,返回剩余的部分. <!DOCTYPE html> <html lang="zh"> & ...

  5. poj1062昂贵的聘礼

    这个题目我最開始看题目看了半天,看不懂.. 可是通过看例子及答案最终看懂了. .. 首先先解决等级的关系. .假设等级越界.则不能交换..所以原本等级的界限是 [rank[1]-m,rank[1]+m ...

  6. WCF实现上传图片功能

    初次学习实现WCF winform程序的通信,主要功能是实现图片的传输. 下面是实现步骤: 第一步: 首先建立一个类库项目TransferPicLib,导入wcf需要的引用System.Service ...

  7. Mqtt协议IOS端移植2

    MqttFramework.h #import <Foundation/Foundation.h> #import "MQTTClient.h" #import &qu ...

  8. setpgid()

    #include<unistd.h> int setpgid(pid_t pid,pid_t pgid); 函数作用:将pid进程的进程组ID设置成pgid,创建一个新进程组或加入一个已存 ...

  9. MySQL_常用SQL语句

    1.按小时统计的语句 select concat(date_format(gmt_create, "%Y-%m-%d %k:00~"), hour(gmt_create)+1, & ...

  10. Android内容提供者

    一个应用中的数据库对别人是不会提供直接的访问的,而是提供接口给别人访问,但是一般应用开发的时候都是去获取别人的数据,而不是自己提供数据. 继承ContentProvider: 在Menifest中注册 ...