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 ...
随机推荐
- 2017.6.27 jdbc基本使用
参考来自:http://www.runoob.com/w3cnote/jdbc-use-guide.html 1.jdbc的执行流程 JDBC API 允许用户访问任何形式的表格数据,尤其是存储在关系 ...
- 使用Kinect2作为Oculus游戏应用的输入设备
注: 文章写于2015年8月, 眼下VR游戏Demo已经完结, 所以把上一次预研的一些经验分享出来, 希望对大家有所帮助 背景 初接触Oculus时, 从网上下载了一大堆的Demo来体验, 可是, 操 ...
- Cocos2d-x 3.2 大富翁游戏项目开发-第七部分 获取角色路径_2
在编写获取路径方法前,我们先把角色须要的动画文件载入进来,角色的文件为png 和 plist格式. player1_anim.png.plist player1_anim.pn ...
- Angular 学习笔记——ng-repeat 隔行换色
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <met ...
- wps文档忘记保存关闭了怎么恢复
wps文档忘记保存关闭了怎么恢复 点击程序左上角的''WPS文字/表格/演示''选择备份管理,根据需要尝试右侧下面的"查看其他备份"功能就能找了. 点击"开始-运行&qu ...
- Archlinux: 优化触摸板配置
在逛 Archlinuxcn BBS 时看到这个帖子: fcitx 输入法看不到选词,上面键盘也不见了! 等待妹子的 依云 提到了 infinality, 并且给出了这个链接: fix-infinal ...
- (八)Thymeleaf的 th:* 属性之—— 模板布局& th:with& 属性优先级
3.7 模板布局 模板名称:layout.html 3.7.1 th:fragment e.g.模板名为footer.html页面body部分如下: <body> <div th:f ...
- Socket协议通讯
Socket协议通讯 服务器端代码: using System; using System.Collections.Generic; using System.ComponentModel; us ...
- Smarty Caching缓存 ¥ 我要打赏
Smarty Caching缓存 https://www.yiibai.com/smarty/smarty_caching.html https://www.w3cschool.cn/smarty/s ...
- Android实践--监測网络状态
Android 监測网络状态 我们在使用Android手机时候,一些APP须要网络环境才干执行,所以手机须要可用的网络,无论是2G.3G或者WIFI.甚至有一些比較耗流量的APP仅仅能在WI ...