Django之stark组件1
stark组件
stark组件是根据Django admin为原型写的一个组件,能够让我们告别增删改查.stark组件是可插拔试的组件,
移植性强,而且只用配置文件就能够得到想要的数据
一、stark组件路由分发
admin用这一条路由就实现了注册表单*4的url。
路由分发的原理:
- 知识一:admin之路由分发原理:
- def text01(request):
- return HttpResponse('text01')
- def text02(request):
- return HttpResponse('text02')
- def text03(request):
- return HttpResponse('text03')
- urlpatterns = [
- path('chen/',(
- [path('text01/',text01),
- path('text02/',text02),
- path('text03/',text03),
- ],
- None,None))
- ]
- 由一个路由分发出来三个 第一个none是namespace,第二个是项目名称
- 一级:
- path('chen/',(
- [
- path()
- path()
- path()
- ],None,None))
- 由一个路由分发出来三个,第一个路由又可以分发出来两个,二级路由.
- 第一个none是namespace,第二个是项目名称
- 二级:
- path('chen/',(
- [
- path(
- [
- path(),
- path(),
- ],None,None))
- ]
- ,None,None))
路由分发原理
单例模式:
***公共的数据***
一个类只允许实例一个对象
***为了数据统一****
怎么生成单例模式?
方式一:__new__
- __new__
- class Singleton(object):
- _instance = None
- def __new__(cls, *args, **kwargs):
- # 第一次生成对象的时候走:
- if not cls._instance:
- cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
- # 第二次走的时候直接走这里
- return cls._instance
- class MyClass(Singleton):
- a = 1
- #那么每次实例对象的时候都是指向 同一个内存地址.
- #实例MyClass的时候都是 同一个对象
方式二:python模块
python模块是天然的单例模式:
1.不管模块哪里导入,只要是再次导入都是从.pyc导入,都是一个内存地址
因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,
就会直接加载 .pyc 文件,而不会再次执行模块代码。
2.我们只需把模块的对象实例化,每次调用的时候都调用这个对象,就可以获得一个单例对象了。
- class StarkSite(object):
- """注册model对应的配置类(MondelStark或用户自定制)"""
- def __init__(self):
- self._registry={}
- #self--->site单例对象
- def register(self,model,stark_class=None):
- if not stark_class:
- stark_class=MondelStark
- self._registry[model] = stark_class(model,self)
- def get_urls(self):
- # self--->site单例对象
- temp=[]
- for model,stark_class_obj in self._registry.items():
- model_name=model._meta.model_name
- app_label =model._meta.app_label
- temp.append(path('%s/%s/'%(app_label,model_name),stark_class_obj.get_url_dispath))
- '''
- path('repository/book/'BookStark(book,).get_url_dispath)
- path('repository/author/'BookStark(author,).get_url_dispath)
- '''
- return temp
- @property
- def urls(self):
- return self.get_urls(),None,None
- site=StarkSite()
单例
每次调用site就是单例对象
说完单例模式,再说回路由的分发:
stark.site就是一个单例,里面进行注册我们的models
为什么我们要用单例模式???
为了能够把model注册到同一个对象里面,我们就可以实现数据统一调度。
StarkSite形成单例类的代码:
- #单例的类
- class StarkSite(object):
- """注册model对应的配置类(MondelStark或用户自定制)"""
- def __init__(self):
- self._registry={}
- #self--->site单例对象
- def register(self,model,stark_class=None):
- if not stark_class:
- stark_class=MondelStark
- self._registry[model] = stark_class(model,self)
- def get_urls(self):
- # self--->site单例对象
- temp=[]
- for model,stark_class_obj in self._registry.items():
- model_name=model._meta.model_name
- app_label =model._meta.app_label
- temp.append(path('%s/%s/'%(app_label,model_name),stark_class_obj.get_url_dispath))
- '''
- path('repository/book/'BookStark(book,).get_url_dispath)
- path('repository/author/'BookStark(author,).get_url_dispath)
- '''
- return temp
- @property
- def urls(self):
- return self.get_urls(),None,None
在register()方法里面,我们在注册的前提
大前提!!!!!!!
***思考***
我们里在直接调用这个register方法?
那么里面注册了数据了吗?
答案是没有的,
***思路***
在每次开启项目的时候,能够自动执行某个py文件进行注册
- from repository import models
- from stark.server.stark import site
- from stark.server.stark import MondelStark
引入
- #我们需要在stark项目的app里:
- from django.apps import AppConfig
- from django.utils.module_loading import autodiscover_modules
- class StarkConfig(AppConfig):
- name = 'stark'
- def ready(self):
- autodiscover_modules('stark',)
- #每次启动都会执行每个项目的stark.py文件,那么一开启项目就把model注册了.
- ###########其他项目注册model##########
- site.register(models.Book,BookStark)
- site.register(models.Author,AuthorStark)
- site.register(models.publish)
自动执行py文件
在其他项目stark.py我们可以自己进行配置类的书写
- from stark.server.stark import MondelStark
- class BookStark(MondelStark):
- pass
如何通过模型类获得字符串名称,和该模型所在的app名称:
我们需要构建的是一级分发:
第一个是model所属项目的名称/第二个是model类的类名
(path('%s/%s'%(app_label,model_name),))
- for model,class_obj in admin.site._registry.items():
- print(model._meta.model_name) #打印出该模型的名称
- print(model._meta.app_label) #打印出该模型的app的名称
二级分发我们需要写在配置类里面:
为什么不能写在单例?
从图中可以看出,如果是单例对象的话,每个model类对应的视图函数都是一样的
我们想要的是每一个model类都需要4个视图函数,
所以我们只能把二级分发放在配置类里面,让每个配置类都生成四个相对应的视图函数
- def url_dispath(self):
- # self--->stark_class_obj--->每一个单独的配置类.
- temp = []
- model_name = self.model._meta.model_name
- app_label = self.model._meta.app_label
- temp.extend([path('add/', self.add_view,name="%s_%s_add"%(app_label,model_name)),
- re_path('^(\d+)/delete/', self.delete_view,name="%s_%s_delete"%(app_label,model_name)),
- re_path('^(\d+)/change/', self.change_view,name="%s_%s_change"%(app_label,model_name)),
- path('', self.show_list,name="%s_%s_list"%(app_label,model_name))])
- return temp
- #起别名,目的是为了反向查询的时候能够查到相对应的url
二级分发
构建表结构:
自定制表头:
配置类继承了MondelStark的配置类
- class BookStark(MondelStark):
- list_display=['id','name','price']
- site.register(models.Book,BookStark)
构建表格
构建表头知识补充:
#如果客户自定制了配置list_display 那么实例化的时候就先在用户自定义的类里面找
#有则返回给后端......没有再去他的父类里面找list_display为空.
属性的反射
属性和方法都可以进行反射
- ###################
- 反射:
- class B(object):
- def__init__(self,name):
- self.name=name
- chen=B('chenxuming')
- s='name'
- ret=getattr(chen,s)
- print(ret) ---->'chenxuming'
属性的反射
如何将表头换成中文:
val = self.config.model._meta.get_field(field).verbose_name
header_list.append(val)
- class Book(models.Model):
- name = models.CharField(max_length=64,verbose_name='书名')
- price= models.IntegerField()
- name=Book._meta.get_field('name')
- #name拿到的是title字段的对象
- print(name)
- print(type(name))
- #可以取里面的属性
- name.max_length --->64
- name.verbose_name--->'书名'
#判断是否是函数的字段
if callable():
from django.utils.safestring import mark_safe
mark_safe(安全调用标签)
构建表格的代码
- def new_list_display(self):
- ''''构建初始化列表的字段''
- temp=[]
- temp.append(MondelStark.checkbox)
- temp.extend(self.list_display)
- temp.append(MondelStark.get_delete_msg)
- if not self.list_display_links:
- temp.append(MondelStark.get_edit_msg)
- return temp
- def get_headers(self):
- # 构建表头: self.new_list_display=[checkbox,'name','price',delete,edit]
- header_list = []
- for field in self.config.new_list_display:
- if callable(field):
- val = field(self.config, header=True)
- header_list.append(val)
- else:
- if field == '__str__':
- val = self.config.model_name.upper()
- header_list.append(val)
- else:
- val = self.config.model._meta.get_field(field).verbose_name
- header_list.append(val)
- return header_list
- def get_body(self):
- # 表数据的创建
- new_list = []
- for obj in self.data_list:
- item_list = []
- for item in self.config.new_list_display:
- if callable(item):
- val = item(self.config, obj)
- else:
- val = getattr(obj, item)
- if item in self.config.list_display_links:
- val = mark_safe('<a href="%s">%s</a>' % ( self.config.get_edit_url(obj), val))
- item_list.append(val)
- new_list.append(item_list)
- return new_list
- [[数据],[数据],[数据]]
- ##########表头,部分表数据的函数#########
- def checkbox(self,obj=None,header=False):
- if header:
- return mark_safe('<input id="choice_all" type="checkbox">')
- return mark_safe('<input class="item" type="checkbox" name="selected_id" value="%s">'%obj.id)
- def get_edit_msg(self,obj=None,header=False):
- if header:
- return "操作"
- _url=self.get_edit_url(obj)
- return mark_safe('<a href="%s">编辑</a>' % _url)
- def get_delete_msg(self,obj=None,header=False):
- if header:
- return "操作"
- _url=self.get_delete_url(obj)
- return mark_safe('<a href="%s">删除</a>'%_url)
构建表格
增:
增和改都是基于ModelForm来实现的。
如果用户自定制
- Stark_Model_Form=自定制modelform的类名
- class BookStark(MondelStark):
- list_display=['id','name','price']
- Stark_Model_Form=ModelFormBook
- list_display_links = ['name']
- class ModelFormBook(ModelForm):
- """自定制ModelForm类"""
- class Meta:
- model=models.Book
- fields='__all__'
- labels={
- 'name':'书名',
- 'price':'价格',
- 'pub':'出版社',
- 'author':'作者',
- }
- def get_model_class(self):
- '''判断是否自定制了ModelForm'''
- if not self.Stark_Model_Form:
- from django.forms import ModelForm
- class ModelDeMo(ModelForm):
- class Meta:
- model = self.model
- fields = '__all__'
- return ModelDeMo
- else:
- return self.Stark_Model_Form
- def add_view(self,request):
- '''增加的视图函数'''
- # self--->stark_class_obj--->每一个单独的配置类.
- ModelDeMo=self.get_model_class()
- if request.method=='GET':
- form =ModelDeMo()
- return render(request, 'oprate/add.html', {'form':form})
- if request.method=='POST':
- form = ModelDeMo(request.POST)
- if form.is_valid():
- form.save()
- return redirect(self.get_list_url())
- else:
- return render(request,'oprate/add.html',{'form':form})
- ###########前端#########
- <form class="form-horizontal col-sm-7" method="post" novalidate>
- {% csrf_token %}
- {% for data in form %}
- <label>{{ data.label }}</label>
- {{ data }}
- <div class="errors-form">{{ data.errors.0 }}</div>
- {% endfor %}
- <button type="submit" class="btn btn-success">提交</button>
- </form>
add
改:
和增加差不多
- def change_view(self,request,nid):
- '''改 视图函数'''
- # self--->stark_class_obj--->每一个单独的配置类.
- ModelDeMo=self.get_model_class()
- change_obj=self.model.objects.filter(id=nid).first()
- if request.method=='GET':
- form=ModelDeMo(instance=change_obj)
- return render(request,'oprate/edit.html',{'form':form})
- if request.method=='POST':
- show_url = self.get_list_url()
- #instance=change_obj
- # form.save()
- #执行的是update操作
- form=ModelDeMo(data=request.POST,instance=change_obj)
- if form.is_valid():
- form.save()
- return redirect(show_url)
- else:
- return render(request, 'oprate/edit.html', {'form': form})
- ###前端###
- <form class="form-horizontal col-sm-7" method="post" novalidate>
- {% csrf_token %}
- {% for data in form %}
- <label>{{ data.label }}</label>
- {{ data }}
- <div class="errors-form">{{ data.errors.0 }}</div>
- {% endfor %}
- <button type="submit" class="btn btn-success">提交</button>
- </form>
change
删:
删要注意的是需要跳转到一个页面,确保用户误点
- def delete_view(self,request,nid):
- # 删除视图函数
- # self--->stark_class_obj--->每一个单独的配置类.
- del_obj = self.model.objects.filter(id=nid).first()
- show_url = self.get_list_url()
- if request.method=='GET':
- return render(request,'oprate/delete.html',{'show_url':show_url})
- if request.method=='POST':
- if del_obj:
- del_obj.delete()
- return redirect(show_url)
- ###前端######
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <h1>删除页面</h1>
- <form action="" method="post" novalidate>
- {% csrf_token %}
- <input type="submit" value="确认删除">
- <a href="{{ show_url }}">取消</a>
- </form>
- </body>
- </html>
search
用户能够自己配置进行模糊查询
Q方法的补充
- from django.db.models import Q
- Q的两种玩法:
- 第一种:
- 查询字段必须是字段
- Book.objects.filter(Q(title='yuan')|Q(price=123))
- 第二种
- 查询字段可以是字符串:
- #实例化一个Q对象
- search_connction=Q()
- #或查询默认是and
- search_connction.connector='or'
- for search_fiile in self.search_fiile #self.search_fiile 用户自定制的['name','price']
- #append里面是一个元组
- #search_connction.children.append((search_fiile,'查询的内容'))
- search_connction.children.append((search_fiile+'__contains','查询的内容'))模糊查询
- data_list = self.model.objects.filter(search_list)
Q两种方法
stark实现search
需要自定制字段:
- search_fields = ['name']
- def get_search_connection(self,request):
- '''获取模糊查询的Q'''
- self.key_word=request.GET.get('q','')
- search_connction=Q()
- if self.key_word:
- search_connction.connector='or'
- for fields in self.search_fields:
- search_connction.children.append((fields+'__icontains',self.key_word))
- return search_connction
- search_list=self.get_search_connection(request)
- data_list = self.model.objects.filter(search_list)
- ##前端##
- {% if showlist.config.search_fields %}
- <form action="" method="get" class="pull-right">
- <input type="text" name="q" value="{{ showlist.config.key_word }}"><button>查询</button>
- </form>
- {% endif %}
Django之stark组件1的更多相关文章
- 【django之stark组件】
一.需求 仿照django的admin,开发自己的stark组件.实现类似数据库客户端的功能,对数据进行增删改查. 二.实现 1.在settings配置中分别注册这三个app # Applicatio ...
- django 之 stark组件
----------------------------------------------------------------烦恼没完没了,内心动荡不安,呜呼哀哉. 一.有个特殊的需求,需要用sta ...
- Django之stark组件
现在让我说啥是stark组件,我也说不清楚.反正从今天讲的知识来看,今天完成的就是自己写一个模块,这个模块包含了admin后台管理工具的一些比较好用的功能,我们把它提炼出来,也就是相当于自己写一个ad ...
- Django之stark组件的使用和总结
Stark组件的使用 组件的字段 list_display=[] 需要显示的字段 list_display_links=[] #需要链接编辑字段 Stark_Model_Form=[] #设置Mode ...
- Django之stark组件2
action批量处理功能 用户可以自定义批量处理功能,但是默认的有批量删除功能. ***思路*** 1,定义一个列表用来装action的类名并extend用户自定义列表 2.循环该列表获取到函数名(用 ...
- stark组件之pop操作【模仿Django的admin】
一.先看下什么django的admin的pop到底是个什么东西 其实就是这么一个东西, a.在添加页面,在一对多和多对多的项后加了一个+号 b.点击这个加号,会弹出对应的添加 页面,在新的添加 c.添 ...
- stark组件之批量操作【模仿Django的admin】
一.先看下django的admin是如何实现批量操作 首先在配置类中定义一个函数 然后我们为这个函数对象设置一个属性,这个属性主要用来显示在select标签中显示的文本内容 最后把函数对象放到一个ac ...
- stark组件之搜索【模仿Django的admin】
一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...
- stark组件之路由分发【模仿Django的admin】
一.先看下django的admin是如何进行路由分发的 1.先看下django的admin的url路径有哪些 其实很简单,假如有一个书籍表,那么每张表对应四个url,增.删.改.查 查看的url ht ...
随机推荐
- 模拟服务器MockServer之Moco详细介绍
转载:http://blog.csdn.net/vite_s/article/details/54583243 前面一篇介绍了如何用mockito来测试我们的一些异步任务,例如网络请求时候的异步回调. ...
- Oracle基础(一) Oracle的安装和卸载
一.数据库的基本概念. 数据库就是数据存储的仓库,可以更快的查询.处理.统计数据,还可以保持数据的一致性.共享性和安全性,方便只能的分析,产生新的有用的信息. 1.数据库的发展阶段: (1)萌芽阶段: ...
- 怎样取消Macbook上顽固的开机启动项
博主遇到的一个顽固启动项是Cisco Anyconnect.我仅仅是偶尔须要使用VPN.可是安装了Cisco Anyconnect之后,每次开机它都会启动,非常烦人. 1 通过系统设置 首先,博主希望 ...
- lodash 数组裁剪 drop
_.drop(array, [n=1]) 裁剪数组中的前 N 个数组,返回剩余的部分. <!DOCTYPE html> <html lang="zh"> & ...
- poj1062昂贵的聘礼
这个题目我最開始看题目看了半天,看不懂.. 可是通过看例子及答案最终看懂了. .. 首先先解决等级的关系. .假设等级越界.则不能交换..所以原本等级的界限是 [rank[1]-m,rank[1]+m ...
- WCF实现上传图片功能
初次学习实现WCF winform程序的通信,主要功能是实现图片的传输. 下面是实现步骤: 第一步: 首先建立一个类库项目TransferPicLib,导入wcf需要的引用System.Service ...
- Mqtt协议IOS端移植2
MqttFramework.h #import <Foundation/Foundation.h> #import "MQTTClient.h" #import &qu ...
- setpgid()
#include<unistd.h> int setpgid(pid_t pid,pid_t pgid); 函数作用:将pid进程的进程组ID设置成pgid,创建一个新进程组或加入一个已存 ...
- MySQL_常用SQL语句
1.按小时统计的语句 select concat(date_format(gmt_create, "%Y-%m-%d %k:00~"), hour(gmt_create)+1, & ...
- Android内容提供者
一个应用中的数据库对别人是不会提供直接的访问的,而是提供接口给别人访问,但是一般应用开发的时候都是去获取别人的数据,而不是自己提供数据. 继承ContentProvider: 在Menifest中注册 ...