10.19stark组件开发(三)

时间:2022-09-02 16:35:35

  2018-10-19 15:42:15

2018-10-19 18:21:33

我觉得现在主要是学一种解决问题的思路,也就是逻辑或者说是算法!!!!

要有对代码的感触!要用面向对象对类进行封装!!Django源码写的就是很6

明天看完stark 然后整理Django !!周末啦!

过不久还得回学校!!!难得的在家清静!珍惜吧!

越努力,越幸运!!!永远不要高估自己!!

.model._meta的用法!

通过字段获取QuerySet对象

10.19stark组件开发(三)

通过字段获取 app和表的名字!

model_name = self.model._meta.model_name
app_label = self.model._meta.app_label 这次新增了自定义过滤功能!
新学了上面两个知识点!
在源码上都有相应的注释!很好看懂!
不难就是有点绕!! server/stark.py
from django.conf.urls import url
from django.shortcuts import render, redirect
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.forms import ModelForm
from stark.utils.page import Pagination
from django.db.models import Q
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.related import ManyToManyField
import copy class ShowList(object):
# 这是一个配置类的对象初始化
def __init__(self, config, data_list, request):
self.config = config
self.data_list = data_list
self.request = request
# 分页
data_count = self.data_list.count()
current_page = int(self.request.GET.get("page", 1))
base_path = self.request.path
self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=3, pager_count=11,)
self.page_data = self.data_list[self.pagination.start:self.pagination.end]
# actions 获取actions这个配置类的列表
self.actions = self.config.actions # [patch_init,] # 处理filter字段连接
def get_filter_linktags(self):
"""用了两次for循环,在算法上有点缀余!不过可以用类或函数封装只是懒-.-能力欠缺!"""
print("list_filter:", self.config.list_filter)
link_dic = {}
for filter_field in self.config.list_filter: # ["title","publish","authors",]
params = copy.deepcopy(self.request.GET)
cid = self.request.GET.get(filter_field, 0)
print("filter_field", filter_field) # "publish"
# 通过_meta.get_field方法,获取该表名对象
filter_field_obj = self.config.model._meta.get_field(filter_field) print("filter_field_obj", filter_field_obj)
print(type(filter_field_obj))
# print("rel...",filter_field_obj.rel.to.objects.all()) # 判断一下 如果是多对多或一对多类型的
if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
# 拿到表的所有QuerySet对象
data_list = filter_field_obj.rel.to.objects.all() # 【publish1,publish2...】
else:
# 这个则是自定义过滤字段
data_list = self.config.model.objects.all().values("pk", filter_field)
print("data_list", data_list) temp = []
# 处理 全部标签
if params.get(filter_field):
# 如果url如果存在参数 则del
del params[filter_field]
temp.append("<a href='?%s'>全部</a>" % params.urlencode())
else:
# 反之加上class 增加颜色
temp.append("<a class='active' href='#'>全部</a>") # 处理 数据标签
for obj in data_list:
# 循环列表中每个QuerySet的对象然后取到相应的值
if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
pk = obj.pk
text = str(obj)
params[filter_field] = pk
else: # data_list= [{"pk":1,"title":"go"},....]
pk = obj.get("pk")
text = obj.get(filter_field)
params[filter_field] = text _url = params.urlencode()
if cid == str(pk) or cid == text:
link_tag = "<a class='active' href='?%s'>%s</a>" % (_url, text)
else:
link_tag = "<a href='?%s'>%s</a>" % (_url, text)
temp.append(link_tag) link_dic[filter_field] = temp
return link_dic # 获取下拉框 用户配置的action_list
def get_action_list(self):
temp = []
for action in self.actions:
# [{"name":""patch_init,"desc":"批量初始化"}]
temp.append({
"name": action.__name__,
"desc": action.short_description
})
return temp # 构建表头
def get_header(self):
header_list = []
print("header", self.config.new_list_play())
# [checkbox,"pk","name","age",edit ,deletes] 【checkbox ,"__str__", edit ,deletes】
for field in self.config.new_list_play(): if callable(field):
# header_list.append(field.__name__)
val = field(self.config, header=True)
header_list.append(val) else:
if field == "__str__":
header_list.append(self.config.model._meta.model_name.upper())
else:
# header_list.append(field)
val = self.config.model._meta.get_field(field).verbose_name
header_list.append(val)
return header_list # 构建表单数据
def get_body(self):
# 构建表单数据
new_data_list = []
for obj in self.page_data:
temp = []
for filed in self.config.new_list_play(): # ["__str__",] ["pk","name","age",edit]
if callable(filed):
val = filed(self.config, obj)
else:
field_obj = self.config.model._meta.get_field(filed)
if isinstance(field_obj, ManyToManyField):
# getattr()仅取到Object, 然后.all() 则可以取到对象
ret = getattr(obj, filed).all()
t = []
for obj in ret:
t.append(str(obj))
val = ",".join(t) else:
val = getattr(obj, filed)
if filed in self.config.list_display_links:
# "app01/userinfo/(\d+)/change"
_url = self.config.get_change_url(obj)
val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) temp.append(val) new_data_list.append(temp)
return new_data_list class ModelStark(object):
# 默认的list_play[]
list_display = ["__str__", ]
list_display_links = []
modelform_class = None
search_fields = []
actions = []
list_filter = [] def __init__(self, model, site):
self.model = model
self.site = site # 默认的批量删除action
def patch_delete(self, request, queryset):
queryset.delete()
patch_delete.short_description = "批量删除" # 配置表头: 删除 编辑,复选框
def edit(self, obj=None, header=False):
"""编辑"""
if header:
return "操作"
# return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
_url = self.get_change_url(obj)
return mark_safe("<a href='%s'>编辑</a>" % _url) def deletes(self, obj=None, header=False):
"""删除"""
if header:
return "操作"
# return mark_safe("<a href='%s/change'>编辑</a>"%obj.pk)
_url = self.get_delete_url(obj)
return mark_safe("<a href='%s'>删除</a>" % _url) def checkbox(self, obj=None, header=False):
"""复选框"""
if header:
return mark_safe('<input id="choice" type="checkbox">')
# value的值不能写死,
return mark_safe('<input class="choice_item" type="checkbox" name="selected_pk" value="%s">' % obj.pk) # 获取配置类的表头信息
def get_modelform_class(self):
"""获取表的配置类"""
if not self.modelform_class:
# 如果表的配置类为空
class ModelFormDemo(ModelForm):
class Meta:
model = self.model
fields = "__all__"
labels = {
""
}
return ModelFormDemo
else:
return self.modelform_class # 添加的视图函数
def add_view(self, request):
ModelFormDemo = self.get_modelform_class()
if request.method == "POST":
form = ModelFormDemo(request.POST)
if form.is_valid():
form.save()
return redirect(self.get_list_url()) return render(request, "add_view.html", locals()) form = ModelFormDemo() return render(request, "add_view.html", locals()) # 删除的视图函数
def delete_view(self, request, id):
url = self.get_list_url()
if request.method == "POST":
self.model.objects.filter(pk=id).delete()
return redirect(url)
return render(request, "delete_view.html", locals()) # 编辑的视图函数
def change_view(self, request, id):
ModelFormDemo = self.get_modelform_class()
edit_obj = self.model.objects.filter(pk=id).first()
if request.method == "POST":
form = ModelFormDemo(request.POST, instance=edit_obj)
if form.is_valid():
form.save()
return redirect(self.get_list_url())
return render(request, "add_view.html", locals())
form = ModelFormDemo(instance=edit_obj)
return render(request, "change_view.html", locals()) # 搜索的视图函数
def get_serach_conditon(self, request):
key_word = request.GET.get("q", "")
self.key_word = key_word
search_connection = Q()
if key_word:
# self.search_fields # ["title","price"]
search_connection.connector = "or"
# 用Q的这种添加方法可以添加字符串
for search_field in self.search_fields:
# search_field+"__contains" ----> title__contains="o" 就是title字段里面包含字母o的
search_connection.children.append((search_field + "__contains", key_word))
return search_connection # 过滤filter的视图函数
def get_filter_condition(self, request):
filter_condition = Q()
for filter_field, val in request.GET.items():
if filter_field in self.list_filter:
filter_condition.children.append((filter_field, val))
return filter_condition # 查看的视图函数
def list_view(self, request):
if request.method == "POST": # action
print("POST:", request.POST)
action = request.POST.get("action") # patch_init
selected_pk = request.POST.getlist("selected_pk")
action_func = getattr(self, action)
queryset = self.model.objects.filter(pk__in=selected_pk)
ret = action_func(request, queryset)
# return ret
# 获取search的Q对象
search_connection = self.get_serach_conditon(request) # 获取filter构建Q对象
filter_condition = self.get_filter_condition(request) # 筛选获取当前表所有数据
data_list = self.model.objects.all().filter(search_connection).filter(filter_condition) # 【obj1,obj2,....】 # 按这ShowList展示页面
showlist = ShowList(self, data_list, request) # 构建一个查看URL
add_url = self.get_add_url()
return render(request, "list_view.html", locals()) # 获取用户配置类里面的list_play[]
def new_list_play(self):
temp = []
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
if not self.list_display_links:
temp.append(ModelStark.edit)
temp.append(ModelStark.deletes)
return temp # 获取用户配置类里面的actions 这个列表
def new_actions(self):
temp=[]
temp.append(ModelStark.patch_delete)
temp.extend(self.actions)
return temp """把url进行反向解析,解耦到各自的函数中,函数中直接返回了对应的url"""
# 获取修改页面的url
def get_change_url(self, obj):
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,)) return _url # 获删除改页面的url
def get_delete_url(self, obj):
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,)) return _url # 获取添加页面的url
def get_add_url(self): model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_add" % (app_label, model_name)) return _url # 获取查看页面的url
def get_list_url(self): model_name = self.model._meta.model_name
app_label = self.model._meta.app_label _url = reverse("%s_%s_list" % (app_label, model_name)) return _url # 二级url分发函数
def get_urls_2(self):
temp = []
model_name = self.model._meta.model_name
app_label = self.model._meta.app_label
temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name)))
temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name)))
temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name)))
temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
return temp @property
def urls_2(self):
print(self.model)
return self.get_urls_2(), None, None class StarkSite(object):
def __init__(self):
self._registry = {} def register(self, model, stark_class=None):
if not stark_class:
stark_class = ModelStark self._registry[model] = stark_class(model, self) # 一级分发url函数
def get_urls(self):
temp = []
for model, stark_class_obj in self._registry.items():
model_name = model._meta.model_name
app_label = model._meta.app_label
# 分发增删改查
temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2)) '''
url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
url(r"^app01/book/",ModelStark(Book).urls_2), '''
return temp @property
def urls(self): return self.get_urls(), None, None # 创建stark的一个单例对象
site = StarkSite()

app01/stark.py

from stark.service.stark import site,ModelStark

from django.urls import reverse
from .models import * from django.utils.safestring import mark_safe from django.forms import ModelForm
from django.forms import widgets as wid class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__" labels={
"title":"书籍名称",
"price":"价格"
} from django.shortcuts import HttpResponse class BookConfig(ModelStark):
# 自定义展示列表
list_display = ["title","price","publishDate","publish","authors"]
# 自定义设置字段为连接
list_display_links = ["title"]
modelform_class=BookModelForm
# 自定义搜索字段
search_fields=["title","price"] def patch_init(self, request, queryset):
print(queryset)
queryset.update(price=123) return HttpResponse("批量初始化OK") patch_init.short_description = "批量初始化" # 自定义处理函数
actions = [patch_init] # 自定义筛选字段
list_filter=["title","publish","authors",] site.register(Book,BookConfig) site.register(Publish)
site.register(Author)
site.register(AuthorDetail)

list.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script> <style>
.filter a{
text-decoration: none;
color: grey;
} .active{
color: rebeccapurple!important;
}
</style>
</head>
<body> <h4>数据列表</h4> <div class="container">
<div class="row">
<div class="col-md-9">
<a href="{{ add_url }}" class="btn btn-primary">添加数据</a> {% if showlist.config.search_fields %}
<form action="" class="pull-right">
<input class="form-control" style="display: inline-block;width:200px" type="text" name="q" value="{{ showlist.config.key_word }}"><button class="btn btn-default">search</button>
</form>
{% endif %} <form action="" method="post">
{% csrf_token %}
<select name="action" class="form-control" id="" style="width: 200px;margin: 8px 2px;display: inline-block;vertical-align: -1px">
<option value="">---------------</option>
{% for item in showlist.get_action_list %}
<option value="{{ item.name }}">{{ item.desc }}</option>
{% endfor %} </select><button type="submit" class="btn btn-success">Go</button>
<table class="table table-bordered table-striped">
<thead>
<tr>
{% for item in showlist.get_header %}
<th>{{ item }}</th>
{% endfor %} </tr> </thead>
<tbody>
{% for data in showlist.get_body %} <tr>
{% for item in data %}
<td>{{ item }}</td>
{% endfor %} </tr>
{% endfor %} </tbody>
</table>
<nav class="pull-right">
<ul class="pagination">
{{ showlist.pagination.page_html|safe }}
</ul>
</nav> </form>
</div> <div class="col-md-3">
<div class="filter">
<h4 style="">Filter</h4>
{% for filter_field,linktags in showlist.get_filter_linktags.items %}
<div class="well">
<p>By {{ filter_field.upper }}</p>
{% for link in linktags %}
<p>{{ link|safe }}</p>
{% endfor %}
</div>
{% endfor %} </div>
</div>
</div>
</div> <script> $("#choice").click(function () { if($(this).prop("checked")){
$(".choice_item").prop("checked",true)
}else {
$(".choice_item").prop("checked",false)
} }) </script>
</body>
</html>

贴上笔记

stark

   分页
分页组件
保存搜索条件 search action filter: print("filter_field",filter_field) # "publish"
filter_field_obj=self.config.model._meta.get_field(filter_field)
print("filter_field_obj",filter_field_obj)
print(type(filter_field_obj))
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.related import ManyToManyField
print("rel...",filter_field_obj.rel.to.objects.all())
self.config.model._meta.get_field(filter_field) 通过字符串找到拿到该名字表的对象
只要属性里面有 (to=) 就可以用
filter_field_obj.rel.to 拿到关联表 class对象