一、filter

效果图

知识点

1.配置得显示Filter,不配置就不显示了
list_filter = ['title','publish', 'authors'] 2.前端显示
后端返回 字典
eg:{"publish":["<a href=''>全部</a>","<a href=''>南京出版社</a>","<a href=''>上海出版社</a>"]
"authors":["<a href=''>全部</a>","<a href=''>yuan</a>","<a href=''>egon</a>"]
} {% if showlist.config.list_filter %}
<h4>Filter</h4>
{% for filter_field, linktags in showlist.get_filter_linktags.items %}
<div class="well">
<p>{{ filter_field.upper }}</p>
{% for link in linktags %}
<p>{{ link|safe }}</p>
{% endfor %} </div>
{% endfor %}
{% endif %} 3.get_filter_linktags 返回 字典
知识:
1.根据字段 str 取到模型得字段对象
filter_field_obj = self.config.model._meta.get_field(filter_field)
model_name = self.config.model._meta.model_name # 模型名 book
app_label = self.config.model._meta.app_label # app名 app01 2.一对多,多对多,
就是 ForeignKey ManyToManyField 得对象
app01.Book.publish
<class 'django.db.models.fields.related.ForeignKey'>
app01.Book.authors
<class 'django.db.models.fields.related.ManyToManyField'> 3.根据一对多,多对多得对象 找关联得模型表,数据
print("rel...", filter_field_obj.rel.to.objects.all())
rel... <QuerySet [<Publish: 南京出版社>, <Publish: 上海出版社>, <Publish: 河北出版社>]>
rel... <QuerySet [<Author: yuan>, <Author: egon>, <Author: alex>]> 4.取数据,普通字段,和关联字段分开取
if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
data_list = filter_field_obj.rel.to.objects.all() # 关联对象 适用 一对多,多对多
else: # 普通字段
data_list = self.config.model.objects.all().values('pk', filter_field) 5.处理全部标签时
注意:url 上面已经有了该field, 全部,就取消该field, del params[filter_field]
url 上面没有,那就没有
temp = []
if params.get(filter_field):
del params[filter_field]
temp.append("<a href='?%s'>全部</a>" % (params.urlencode()))
else:
temp.append("<a href='#' class='active'>全部</a>") 6.处理数据标签
注意:分开处理关联字段和普通字段
params = copy.deepcopy(self.request.GET)
为url加一个params
params[filter_field] = pk
params[filter_field] = text 每一次取数据都要保留 正在访问得 url 并加上正在访问得field! _url = params.urlencode()
link_tag = "<a href='?%s'>%s</a>" % (_url, text) 正在点击得,得加上样式 active
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)
        # 处理数据标签
for obj in data_list:
if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
pk = obj.pk
text = str(obj)
params[filter_field] = pk
else:
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
    def get_filter_linktags(self):
print('list_filter:',self.config.list_filter) # ['title', 'publish', 'authors'] link_dic = {}
import copy for filter_field in self.config.list_filter:
params = copy.deepcopy(self.request.GET) cid = self.request.GET.get(filter_field, 0) filter_field_obj = self.config.model._meta.get_field(filter_field)
print(filter_field_obj)
print(type(filter_field_obj))
"""
app01.Book.title
<class 'django.db.models.fields.CharField'>
app01.Book.publish
<class 'django.db.models.fields.related.ForeignKey'>
app01.Book.authors
<class 'django.db.models.fields.related.ManyToManyField'>
""" 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())
# rel... <QuerySet [<Publish: 南京出版社>, <Publish: 上海出版社>, <Publish: 河北出版社>]>
# rel... <QuerySet [<Author: yuan>, <Author: egon>, <Author: alex>]> if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
data_list = filter_field_obj.rel.to.objects.all() # 关联对象 适用 一对多,多对多
else: # 普通字段
data_list = self.config.model.objects.all().values('pk', filter_field) # 处理全部标签
temp = []
if params.get(filter_field):
del params[filter_field]
temp.append("<a href='?%s'>全部</a>" % (params.urlencode()))
else:
temp.append("<a href='#' class='active'>全部</a>") # 处理数据标签
for obj in data_list:
if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
pk = obj.pk
text = str(obj)
params[filter_field] = pk
else:
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

4.Q查询 and
def list_view(self, request):
...
...
# 获取filter得Q对象
filter_condition = self.get_filter_condition(request) # 筛选当前表得所有数据
data_list = self.model.objects.all().filter(search_connection).filter(filter_condition)
...
... # Q对象
def get_filter_condition(self, request):
filter_condition = Q() # 默认是 and 不是 or, 根据str,查找val
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 补充:
Q查询根据字段
bookList=Book.objects.filter(Q(authors__name="yuan")|Q(authors__name="egon"))
Q查询根据str
filter_condition = Q()
filter_consition.connector = "or" # 如果不写默认是 and
filter_condition.children.append(("title","yuan"))
filter_condition.children.append(("date","2018-12-12")) Book.object.filter(filter_condition)

app01/stark.py

# -*- coding:utf-8 -*-
from stark.service import stark
from .models import *
from django.forms import ModelForm class BookModelForm(ModelForm):
class Meta:
model = Book
fields = "__all__"
labels = {
"title": '书籍名称',
"price": '价格',
'publishDate': '出版日期'
} from django.shortcuts import HttpResponse
class BookConfig(stark.ModelStark): list_display = ['title', 'price','publishDate']
list_display_links = ['title']
modelform_class = BookModelForm
search_fields = ['title', 'price'] def patch_init(self, request, queryset):
# print("queryset",queryset)
queryset.update(price=123) return HttpResponse('批量初始化OK') patch_init.short_description = "批量初始化"
actions = [patch_init] list_filter = ['title','publish', 'authors'] stark.site.register(Book, BookConfig)
stark.site.register(Publish)
stark.site.register(Author)
stark.site.register(AuthorDetail)

stark.py

stark/service/stark.py

from django.conf.urls import url
from django.shortcuts import HttpResponse, reverse, redirect, render
from django.utils.safestring import mark_safe
from django.urls import reverse
from django.forms import ModelForm
from stark.utils.page import Pagination
from django.db.models import Q 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 = 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] self.actions = self.config.new_actions() def get_filter_linktags(self):
print('list_filter:',self.config.list_filter) # ['title', 'publish', 'authors'] link_dic = {}
import copy for filter_field in self.config.list_filter:
params = copy.deepcopy(self.request.GET) cid = self.request.GET.get(filter_field, 0) filter_field_obj = self.config.model._meta.get_field(filter_field)
print(filter_field_obj)
print(type(filter_field_obj))
"""
app01.Book.title
<class 'django.db.models.fields.CharField'>
app01.Book.publish
<class 'django.db.models.fields.related.ForeignKey'>
app01.Book.authors
<class 'django.db.models.fields.related.ManyToManyField'>
""" 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())
# rel... <QuerySet [<Publish: 南京出版社>, <Publish: 上海出版社>, <Publish: 河北出版社>, <Publish: 3>]>
# rel... <QuerySet [<Author: yuan>, <Author: egon>, <Author: alex>]> if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
data_list = filter_field_obj.rel.to.objects.all() # 关联对象 适用 一对多,多对多
else: # 普通字段
data_list = self.config.model.objects.all().values('pk', filter_field) # 处理全部标签
temp = []
if params.get(filter_field):
del params[filter_field]
temp.append("<a href='?%s'>全部</a>" % (params.urlencode()))
else:
temp.append("<a href='#' class='active'>全部</a>") # 处理数据标签
for obj in data_list:
if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
pk = obj.pk
text = str(obj)
params[filter_field] = pk
else:
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 def get_action_list(self):
temp = []
for action in self.actions:
temp.append({
"name": action.__name__,
"desc":action.short_description
}) return temp def get_header(self):
# 构建表头
header_list = []
# header_list = ['选择','pk',...'操作','操作']
for field in self.config .new_list_play():
if callable(field):
val = field(self.config, header=True)
else:
if field == "__str__":
val = self.config .model._meta.model_name.upper()
else: # 根据str 拿字段对象 取中文
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 data in self.page_data:
temp = []
for field in self.config.new_list_play(): # ['title','price'] 字符串找对象得属性 反射
# print('field:', field)
if callable(field):
val = field(self.config, data)
else:
val = getattr(data, field) if field in self.config.list_display_links:
_url = self.config.get_change_url(data)
val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) temp.append(val) new_data_list.append(temp) # [['yuan', 12], ['alex', 18], ['egon', 22]] return new_data_list class ModelStark(object):
list_display = ["__str__"]
list_display_links = []
modelform_class = []
search_fields = []
actions = []
list_filter = [] def __init__(self, model, site):
self.model = model
self.site = site def patch_delete(self, request, queryset):
queryset.delete()
patch_delete.short_description = "批量删除" def edit(self, obj=None, header=False):
if header:
return "操作" _url = self.get_change_url(obj)
return mark_safe("<a href='%s'>编辑</a>" % _url) def deletes(self, obj=None, header=False):
if header:
return '操作' _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'>")
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__"
return ModelFormDemo
else:
return self.modelform_class def add_view(self, request):
ModelFormDemo = self.get_modelform_class()
form = ModelFormDemo() 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()) def delete_view(self, request, delete_id):
url = self.get_list_url() if request.method == 'POST':
self.model.objects.filter(pk=delete_id).delete()
return redirect(url) return render(request, 'delete_view.html', locals()) def change_view(self, request, change_id):
ModelFormDemo = self.get_modelform_class()
edit_obj = self.model.objects.filter(pk=change_id).first()
form = ModelFormDemo(instance=edit_obj) 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,'change_view.html', locals()) def new_list_play(self):
temp = []
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
temp.append(ModelStark.edit)
temp.append(ModelStark.deletes) return temp def new_actions(self):
temp = []
temp.append(ModelStark.patch_delete)
temp.extend(self.actions) return temp def get_change_url(self, obj):
model_name = self.model._meta.model_name
app_lable = self.model._meta.app_label _url = reverse("%s_%s_change" % (app_lable, model_name), args=(obj.pk,)) return _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 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 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 def get_search_condition(self, request):
key_words = request.GET.get('q', "")
self.key_words = key_words
search_connection = Q()
if key_words:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_words)) return search_connection def get_filter_condition(self, request):
filter_condition = Q() # 默认是 and 不是 or
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":
print("request.POST:",request.POST)
# 'action': ['patch_init'], 'selected_pk': ['1', '2']
action = request.POST.get('action')
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 # 获取searchd得Q对象
search_connection = self.get_search_condition(request) # 获取filter得Q对象
filter_condition = self.get_filter_condition(request) # 筛选当前表得所有数据
data_list = self.model.objects.all().filter(search_connection).filter(filter_condition) # 展示数据
showlist = ShowList(self, data_list, request) # 构建一个查看url
add_url = self.get_add_url()
return render(request, 'list_view.html',locals()) def get_urls2(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 urls2(self): return self.get_urls2(), 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) 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.urls2)) return temp @property
def urls(self): return self.get_urls(), None, None site = StarkSite()

stark.py

list_view.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script>
<style type="text/css">
.filter a{text-decoration: none; color: grey}
.active{ color: red!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 type="text" name="q" value="{{ showlist.config.key_words }}"><button>submit</button>
</form>
{% endif %} <form action="" method="post">
{% csrf_token %}
<select name="action" id="" style="width: 200px; padding: 5px 8px; display: inline-block; ">
<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-info">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>
<ul class="pagination">
{{ showlist.pagination.page_html|safe }}
</ul>
</nav> </form> </div> <div class="col-md-3">
{% if showlist.config.list_filter %}
<h4>Filter</h4>
{% for filter_field, linktags in showlist.get_filter_linktags.items %}
<div class="well">
<p>{{ filter_field.upper }}</p>
{% for link in linktags %}
<p>{{ link|safe }}</p>
{% endfor %} </div>
{% endfor %}
{% endif %} </div>
</div>
</div> <script type="text/javascript">
$('#choice').click(function () {
if($(this).prop('checked')){
$('.choice_item').prop('checked',true)
}else{
$('.choice_item').prop('checked',false)
}
}) </script> </body>
</html>

list_view.html

二、pop

效果图

知识点

pop功能:
1.在一对多和多对多字段后渲染 +
2.+对应的跳转路径
3.保存添加记录同时,将原页面的对应的下拉菜单中添加该记录 --------------------------
知识点:
1.在一对多和多对多字段后渲染+
后台需要先判断 是否是 一对多 多对多字段
modelform, 遍历
for bfield in form:
print(bfield.field) # 是每个form字段对象
所以:判断是否是一对多,多对多字段
if isinstance(bfield.field, ModelChoiceField):
bfield.is_pop = True # 为特殊字段加上特有属性,方便前端判断。 注意:ModelMultipleChoiceField(多对多) 继承 ModelChoiceField(一对多)
ModelChoiceField 继承 ChoiceField
    for bfield in form:
print(type(bfield)) # 字段类型
# <class 'django.forms.boundfield.BoundField'> print('name', bfield.name) # 字段名字符串 publish authors from django.forms.boundfield import BoundField
print(bfield.field) # 字段对象
# <django.forms.fields.CharField object at 0x0000014BD355EBA8>
# <django.forms.models.ModelChoiceField object at 0x0000014BD355ECF8>
# <django.forms.models.ModelMultipleChoiceField object at 0x0000014BD355ED68> from django.forms.models import ModelChoiceField
if isinstance(bfield.field, ModelChoiceField):
# 给一对多,多对多字段,对象加个属性is_pop;前端就可以判断在哪个位置加+
bfield.is_pop = True 注意: ModelMultipleChoiceField 继承 ModelChoiceField
所以:只需要判断 isinstance(bfield.field, ModelChoiceField)
2.+对应的跳转路径
form表单得一对多,多对多得字段对象
bfield.field.queryset.model # 相关联得模型!!<class 'app01.models.Publish'>
#(模型表得对象去找 filter_field_obj.rel.to.objects.all(),到to是模型。) 根据queryset找model queryset.model
根据model找queryset model.objects.all() related_model_name = bfield.field.queryset.model._meta.model_name # publish
related_app_label = bfield.field.queryset.model._meta.app_label # app01 反向解析url
_url = reverse("%s_%s_add" % (related_app_label, related_model_name)) # 为bfield添加自己特有的url,
# ?后面是为了,区分是top,还是正常页面打开/add/,方便之后关闭,以及赋值。
bfield.url = _url + "?pop_res_id=id_%s" % bfield.name
    if isinstance(bfield.field, ModelChoiceField):
bfield.is_pop = True print('---',bfield.field.queryset.model)
# <class 'app01.models.Publish'>
# <class 'app01.models.Author'>
related_model_name = bfield.field.queryset.model._meta.model_name
related_app_label = bfield.field.queryset.model._meta.app_label
_url = reverse("%s_%s_add" % (related_app_label, related_model_name))
bfield.url = _url + "?pop_res_id=id_%s" % bfield.name

3.关闭弹出得top页面
top弹出,关闭页面,回到到原页面;
正常添加,跳转到list页面; 返回 res = {"pk":obj.pk, 'text':str(obj), "pop_res_id": pop_res_id}
到pop.html,方便关闭pop页面 pop.html:
关闭以及将接收得数据传到原页面上!
window.opener.pop_response("{{ res.pk}}","{{ res.text }}","{{ res.pop_res_id }}");
window.close()
    # 两种情况
pop_res_id = request.GET.get('pop_res_id')
if pop_res_id:
res = {"pk":obj.pk, 'text':str(obj), "pop_res_id": pop_res_id}
return render(request,'pop.html',{"res":res})
else:
return redirect(self.get_list_url()) <script type="text/javascript">
window.opener.pop_response("{{ res.pk}}","{{ res.text }}","{{ res.pop_res_id }}");
window.close()
</script>
4.原页面接收数据,并显示刚添加得数据(window.opener)
拿到 id, text, pop_res_id
动态创建 option append到对应得下拉框中,并选中;
var $option = $("<option>");
$option.html(text);
$option.val(pk);
$option.attr('selected','selected'); $('#'+pop_res_id).append($option)
    pop.html
window.opener.pop_response("{{ res.pk}}","{{ res.text }}","{{ res.pop_res_id }}");
window.close()

    
add_view.html
<script type="text/javascript">
function pop_response(pk, text,pop_res_id) {
console.log(pk);
console.log(text);
console.log(pop_res_id); // optiond得文本值 和value
var $option = $("<option>"); //<option></option>
$option.html(text);
$option.val(pk);
$option.attr('selected','selected'); $('#'+pop_res_id).append($option)
} </script>

    前端展示:定位,(父相子绝)
<div style="position: relative">
{% if field.is_pop %}
<a onclick="pop('{{ field.url }}')"><span style="font-size: 23px;position: absolute; right: -23px; top: 25px;">+</span></a>
{% endif %}
</div>
def add_view(self, request):
ModelFormDemo = self.get_modelform_class()
form = ModelFormDemo() for bfield in form:
print('i::', type(bfield)) # 字段类型
# print('i::', bfield.field) # 字段对象
# print('name', bfield.name) # 字段名字符串 publish authors # <class 'django.forms.boundfield.BoundField'>
from django.forms.boundfield import BoundField
print(bfield.field)
from django.forms.models import ModelChoiceField
from django.forms.models import ModelMultipleChoiceField
# <django.forms.fields.CharField object at 0x0000014BD355EBA8>
# <django.forms.models.ModelChoiceField object at 0x0000014BD355ECF8>
# <django.forms.models.ModelMultipleChoiceField object at 0x0000014BD355ED68>
from django.forms.models import ModelChoiceField
if isinstance(bfield.field, ModelChoiceField):
bfield.is_pop = True print('---',bfield.field.queryset.model)
# <class 'app01.models.Publish'>
# <class 'app01.models.Author'>
related_model_name = bfield.field.queryset.model._meta.model_name
related_app_label = bfield.field.queryset.model._meta.app_label
_url = reverse("%s_%s_add" % (related_app_label, related_model_name))
bfield.url = _url + "?pop_res_id=id_%s" % bfield.name if request.method == 'POST':
form = ModelFormDemo(request.POST)
if form.is_valid():
obj = form.save() # 两种情况
pop_res_id = request.GET.get('pop_res_id')
if pop_res_id:
res = {"pk":obj.pk, 'text':str(obj), "pop_res_id": pop_res_id}
return render(request,'pop.html',{"res":res})
else:
return redirect(self.get_list_url()) return render(request, 'add_view.html', locals())

补充:

ChoiceFiled
ModelChoiceFiled(ChoiceFiled) ---- select(单选) --- ForeignKey
MultiModelChoiceFiled (ModelChoiceFiled)----select(多选) --- ManyToManyField Book模型,form表单,modelform;
modelform帮我们转成了form表单;
bootstrap页面自适应: col-xs-8
class Book(model.Model):
title = models.CharField(max_length=32)
price = models.IntegerField()
publish=model.Foreignkey("Publish")
authors=model.ManyToMany("Author") from django.forms import ModelForm
class BookForm(ModelForm):
class Meta:
model=Book
fields="__all__" from django import forms
class BookForm(forms.Form):
title=forms.CharField(max_length=32)
price=forms.IntegerField()
publish = forms.ModelChoiceFiled("Publish")
authors = forms.ModelMultipleChoiceField("Author") form=BookForm()

stark/service/stark.py

from django.conf.urls import url
from django.shortcuts import HttpResponse, reverse, redirect, render
from django.utils.safestring import mark_safe
from django.urls import reverse
from django.forms import ModelForm
from stark.utils.page import Pagination
from django.db.models import Q 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 = 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] self.actions = self.config.new_actions() def get_filter_linktags(self):
print('list_filter:',self.config.list_filter) # ['title', 'publish', 'authors'] link_dic = {}
import copy for filter_field in self.config.list_filter:
params = copy.deepcopy(self.request.GET) cid = self.request.GET.get(filter_field, 0) filter_field_obj = self.config.model._meta.get_field(filter_field)
print(filter_field_obj)
print(type(filter_field_obj))
"""
app01.Book.title
<class 'django.db.models.fields.CharField'>
app01.Book.publish
<class 'django.db.models.fields.related.ForeignKey'>
app01.Book.authors
<class 'django.db.models.fields.related.ManyToManyField'>
""" 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())
# rel... <QuerySet [<Publish: 南京出版社>, <Publish: 上海出版社>, <Publish: 河北出版社>, <Publish: 3>]>
# rel... <QuerySet [<Author: yuan>, <Author: egon>, <Author: alex>]> if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
data_list = filter_field_obj.rel.to.objects.all() # 关联对象 适用 一对多,多对多
else: # 普通字段
data_list = self.config.model.objects.all().values('pk', filter_field) # 处理全部标签
temp = []
if params.get(filter_field):
del params[filter_field]
temp.append("<a href='?%s'>全部</a>" % (params.urlencode()))
else:
temp.append("<a href='#' class='active'>全部</a>") # 处理数据标签
for obj in data_list:
if isinstance(filter_field_obj,ForeignKey) or isinstance(filter_field_obj,ManyToManyField):
pk = obj.pk
text = str(obj)
params[filter_field] = pk
else:
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 def get_action_list(self):
temp = []
for action in self.actions:
temp.append({
"name": action.__name__,
"desc":action.short_description
}) return temp def get_header(self):
# 构建表头
header_list = []
# header_list = ['选择','pk',...'操作','操作']
for field in self.config .new_list_play():
if callable(field):
val = field(self.config, header=True)
else:
if field == "__str__":
val = self.config .model._meta.model_name.upper()
else: # 根据str 拿字段对象 取中文
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 data in self.page_data:
temp = []
for field in self.config.new_list_play(): # ['title','price'] 字符串找对象得属性 反射
# print('field:', field)
if callable(field):
val = field(self.config, data)
else:
val = getattr(data, field) if field in self.config.list_display_links:
_url = self.config.get_change_url(data)
val = mark_safe("<a href='%s'>%s</a>" % (_url, val)) temp.append(val) new_data_list.append(temp) # [['yuan', 12], ['alex', 18], ['egon', 22]] return new_data_list class ModelStark(object):
list_display = ["__str__"]
list_display_links = []
modelform_class = []
search_fields = []
actions = []
list_filter = [] def __init__(self, model, site):
self.model = model
self.site = site def patch_delete(self, request, queryset):
queryset.delete()
patch_delete.short_description = "批量删除" def edit(self, obj=None, header=False):
if header:
return "操作" _url = self.get_change_url(obj)
return mark_safe("<a href='%s'>编辑</a>" % _url) def deletes(self, obj=None, header=False):
if header:
return '操作' _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'>")
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__"
return ModelFormDemo
else:
return self.modelform_class def add_view(self, request):
ModelFormDemo = self.get_modelform_class()
form = ModelFormDemo() for bfield in form:
print('i::', type(bfield)) # 字段类型
# print('i::', bfield.field) # 字段对象
# print('name', bfield.name) # 字段名字符串 publish authors # <class 'django.forms.boundfield.BoundField'>
from django.forms.boundfield import BoundField
print(bfield.field)
from django.forms.models import ModelChoiceField
from django.forms.models import ModelMultipleChoiceField
# <django.forms.fields.CharField object at 0x0000014BD355EBA8>
# <django.forms.models.ModelChoiceField object at 0x0000014BD355ECF8>
# <django.forms.models.ModelMultipleChoiceField object at 0x0000014BD355ED68>
from django.forms.models import ModelChoiceField
if isinstance(bfield.field, ModelChoiceField):
bfield.is_pop = True print('---',bfield.field.queryset.model)
# <class 'app01.models.Publish'>
# <class 'app01.models.Author'>
related_model_name = bfield.field.queryset.model._meta.model_name
related_app_label = bfield.field.queryset.model._meta.app_label
_url = reverse("%s_%s_add" % (related_app_label, related_model_name))
bfield.url = _url + "?pop_res_id=id_%s" % bfield.name if request.method == 'POST':
form = ModelFormDemo(request.POST)
if form.is_valid():
obj = form.save() # 两种情况
pop_res_id = request.GET.get('pop_res_id')
if pop_res_id:
res = {"pk":obj.pk, 'text':str(obj), "pop_res_id": pop_res_id}
return render(request,'pop.html',{"res":res})
else:
return redirect(self.get_list_url()) return render(request, 'add_view.html', locals()) def delete_view(self, request, delete_id):
url = self.get_list_url() if request.method == 'POST':
self.model.objects.filter(pk=delete_id).delete()
return redirect(url) return render(request, 'delete_view.html', locals()) def change_view(self, request, change_id):
ModelFormDemo = self.get_modelform_class()
edit_obj = self.model.objects.filter(pk=change_id).first()
form = ModelFormDemo(instance=edit_obj) 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,'change_view.html', locals()) def new_list_play(self):
temp = []
temp.append(ModelStark.checkbox)
temp.extend(self.list_display)
temp.append(ModelStark.edit)
temp.append(ModelStark.deletes) return temp def new_actions(self):
temp = []
temp.append(ModelStark.patch_delete)
temp.extend(self.actions) return temp def get_change_url(self, obj):
model_name = self.model._meta.model_name
app_lable = self.model._meta.app_label _url = reverse("%s_%s_change" % (app_lable, model_name), args=(obj.pk,)) return _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 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 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 def get_search_condition(self, request):
key_words = request.GET.get('q', "")
self.key_words = key_words
search_connection = Q()
if key_words:
search_connection.connector = "or"
for search_field in self.search_fields:
search_connection.children.append((search_field+"__contains", key_words)) return search_connection def get_filter_condition(self, request):
filter_condition = Q() # 默认是 and 不是 or
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":
print("request.POST:",request.POST)
# 'action': ['patch_init'], 'selected_pk': ['1', '2']
action = request.POST.get('action')
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 # 获取searchd得Q对象
search_connection = self.get_search_condition(request) # 获取filter得Q对象
filter_condition = self.get_filter_condition(request) # 筛选当前表得所有数据
data_list = self.model.objects.all().filter(search_connection).filter(filter_condition) # 展示数据
showlist = ShowList(self, data_list, request) # 构建一个查看url
add_url = self.get_add_url()
return render(request, 'list_view.html',locals()) def get_urls2(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 urls2(self): return self.get_urls2(), 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) 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.urls2)) return temp @property
def urls(self): return self.get_urls(), None, None site = StarkSite()

stark.py

add_view.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css">
<script src="/static/js/jquery-1.12.4.min.js"></script>
<style type="text/css">
input,select {
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075);
-webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
-o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
}
.error{
color: red;
} </style> </head>
<body>
<h3>添加页面</h3> {% include 'form.html' %} <script type="text/javascript">
function pop_response(pk, text,pop_res_id) {
console.log(pk);
console.log(text);
console.log(pop_res_id); // optiond得文本值 和value
var $option = $("<option>"); //<option></option>
$option.html(text);
$option.val(pk);
$option.attr('selected','selected'); $('#'+pop_res_id).append($option)
} </script> </body>
</html>

add_view.html

form.html

<div class="container">
<div class="row">
<div class="col-md-6 col-xs-10 col-md-offset-1">
<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div style="position: relative">
<label for="">{{ field.label }}</label>
{{ field }} <span class="error pull-right">{{ field.errors.0 }}</span> {% if field.is_pop %}
<a onclick="pop('{{ field.url }}')"><span style="font-size: 23px;position: absolute; right: -23px; top: 25px;">+</span></a>
{% endif %} </div>
{% endfor %} <button type="submit" class="btn btn-info">btn</button>
</form> </div>
</div> </div>
<script type="text/javascript">
function pop(url) {
window.open(url,"","width=500,height=300,top=100,left=100")
}
</script>

form.html

pop.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <script type="text/javascript">
window.opener.pop_response("{{ res.pk}}","{{ res.text }}","{{ res.pop_res_id }}");
window.close() </script> </body>
</html>

pop.html

三、stark - 总结

总结

(单例,继承,反射,面向对象,modelform 应用得很好!!)

1.注册表
单例模式 site = StarkSite() 2.生成url
url(r'^stark/', ([],None,None)) 3.数据列表展示
可自定义配置显示:
list_display = ["__str__"]
list_display_links = []
modelform_class = []
search_fields = []
actions = []
list_filter = [] 4.增删改页面 modelform 5.分页
自定义分页组件 stark/utils/page.py
class Pagination(object):
...
... 6.search模糊查询
Q查询 or
search_connection = Q()
...
data_list = self.model.objects.all().filter(search_connection) 7.action批量处理
def patch_init(self, request, queryset):
queryset.update(price=123)
...
patch_init.short_description = "批量初始化" actions = [patch_init] queryset = self.model.objects.filter(pk__in=selected_pk) 8.filter过滤
list_filter = ['title','publish', 'authors']
eg:{"publish":["<a href=''>全部</a>","<a href=''>南京出版社</a>","<a href=''>上海出版社</a>"]
"authors":["<a href=''>全部</a>","<a href=''>yuan</a>","<a href=''>egon</a>"]
} Q查询 and
filter_condition = Q()
data_list = self.model.objects.all().filter(search_connection).filter(filter_condition) 9.pop弹出
在一对多和多对多字段后渲染 +
+对应的跳转路径
保存添加记录同时,将原页面的对应的下拉菜单中添加该记录

test.py

from django.test import TestCase

# Create your tests here.

#
# class A(object):
#
# x=12
# def __init__(self,m):
# self.z = m
# def xxx(self):
# print(self.x)
# print(self.z)
#
# class B(A):
# x=5
# z = 11
#
# b=B(10)
# b.xxx() #######################################
#
# class Person(object):
# def __init__(self,name):
# self.name = name
#
# alex = Person('alex')
# print(alex.name)
#
# s = 'name'
#
# # print(alex.s) # 用反射
#
# getattr(alex,s)
#
# print(getattr(alex,s)) #######################################
# 没学面向对象之前,都是函数 , # 函数 方法 # class Person(object):
# def __init__(self,name):
# self.name = name
#
# def eat(self): # 方法!
# print(self)
# print('eating...')
#
# # 实例方法
# # egon = Person('egon')
# # egon.eat()
#
# # 函数
# Person.eat('ss') ####################################### # list = [1,2,3]
# list.append(4)
# print(list)
# list.insert(0,100)
# print(list) #######################################
# li = []
# print(len(li))
#
# s = "sss"
# print(isinstance(s,str)) ####################################### # class Person(object):
# def __init__(self,name):
# self.name = name
#
# def __str__(self):
# return self.name
#
# alex = Person('alex')
# # print(alex.name)
# # print(alex)
#
# print(alex.__str__())
# print(str(alex))
#
# print(getattr(alex,'__str__')()) #######################################
# temp = []
# temp.append(1)
# temp.extend([1,2,3])
# print(temp) ####################################### # def foo():
# return
#
# print(foo.__name__) #######################################
# 查询是字段名称
# Book.objects.filter(Q(title='yuan')|Q(price='123')) # Q() 查询放str,
# q = Q()
# q.connection = 'or'
# q.children.append(('title','yuan'))
# q.children.append(('price',123)) ####################################### # ret = self.model.objects.filter(title__startswith='py')
# ret = self.model.objects.filter(price__in=[123, 111, 21, 11])
# ret = self.model.objects.filter(price__range=[10, 100])
# ret = self.model.objects.filter(title__contains='y')
# ret = self.model.objects.filter(title__contains='o')
# ret = self.model.objects.filter(title__icontains='o')
# print(ret)
# return HttpResponse('ok') ####################################### # def foo():
# print('ok')
#
# print(foo.__name__)
# print(type(foo.__name__))
# foo.desc = '123'
# print(foo.desc)
# a = foo()
# a.desc = 12
# print(a.desc) ####################################### # class A(): # str = "http://127.0.0.1:8000/stark/app01/book/?publish=1&author=5" #######################################
# class A(object):
# pass
#
# class B(A):
# pass
#
# b = B()
# print(isinstance(b,A)) # True
# print(isinstance(b,B)) # True

test.py

code

原始版

  https://github.com/alice-bj/stark_pro_0

简洁版

  https://github.com/alice-bj/stark_admin

stark - filter、pop、总结的更多相关文章

  1. js array filter pop push shift unshift方法

    JavaScript Array filter() 方法  JavaScript Array 对象 实例 返回数组 ages 中所有元素都大于 18 的元素: var ages = [32, 33,  ...

  2. stark组件之pop页面,按钮,url,页面

      1.Window open() 方法 2.admin的pop添加按钮 3.stark之pop功能 3.知识点总结 4.coding代码 1.Window open() 方法 效果图   2.adm ...

  3. 12 stark组件之pop,按钮,url,页面

    1.Window open() 方法 http://www.runoob.com/jsref/met-win-open.html 效果图   2.admin的pop添加按钮 3.stark之pop功能 ...

  4. Django - 学习目录

    Django 基础 web应用/http协议/web框架 Django简介 Django - 路由层(URLconf) Django - 视图层 Django - 模板层 Django - 模型层 - ...

  5. Django之template操作

    一.模板渲染的原理 (一)使用 模板渲染首先有一个模板对象Template,然后有一个上下文对象Context,通过render方法进行渲染,最后返回字符串,render方法的本质还是调用了HttpR ...

  6. 测开之路六十:接口测试平台之common目录

    实现接口测试平台使用jsonpath进行取值来断言,效果: 访问页面: 调试功能:http://www.kuaidi100.com/query 保存功能 触发执行功能 查看报告功能 目录结构 comm ...

  7. 测开之路五十一:代码实现MongoDB增删改查

    初始化时连接.析构时断开连接 from pymongo import MongoClient class Mogo(object): def __init__(self, host='127.0.0. ...

  8. django 操作数据库--orm(object relation mapping)---models

    思想 django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM). PHP:activerecord Java:Hibernate C#:Ent ...

  9. JS中some()和every()和join()和concat()和pop(),push(),shift(),unshfit()和map()和filter()

    一.Array 1.some()和every() some()是对数组中每一项运行指定函数,如果该函数对任一项返回true,则返回true. every()是对数组中的每一项运行给定函数,如果该函数对 ...

随机推荐

  1. Codeforces Round #Pi (Div. 2) —— D One-Dimensional Battle Ships

    题目的意思是: 如今有一个长度为n,宽为1的方格,在上面能够放大小为1*a船,然后输入为n,k,a.分别为平地的大小,船的数量,船的长度. 一个叫alice的人已经在地图上摆好了船的位置. 然后bob ...

  2. iOS 开发系列:CoreData Object 变成 Fault 的一种方式

    @quote: 近来一直与 CoreData 打交道.这是一个架构庞大.学习曲线比較陡峭的 iOS 组件,每次遇到问题都会对其有新的认识. 这次就仅仅讲一点,关于错误认知 Object(NSManag ...

  3. PHP实现金额数字转换成大写函数

    <?php header("Content-Type:text/html;charset=utf-8"); function num_to_upper($num) { $d ...

  4. c++ list sort

      1.  bool operator < (S & b) {      return ID < b.ID;     } struct S { std::string firstn ...

  5. 理解ros话题--6

    理解ROS话题(原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/) Description: 本教程介绍ROS话题(topics)以及如何使用ro ...

  6. jQuery中animate()的方法以及$(&quot;body&quot;).animate({&quot;scrollTop&quot;:top})不被Firefox支持问题的解决

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/50846678 本文出自[我是干勾鱼的博客] jQuery中animate()的方 ...

  7. Int 型数值存储

    1. Int 在计算机中占 4 Byte, 共 32 位, 最大正数为 2147483647, 最小负数为 -2147483648 2. 正数存储在计算机中的形式为原码,最大正数的十六进制形式为 0X ...

  8. 数据库中存储js代码无法json解析

    .net-------------------Microsoft.JScript.GlobalObject.escape(); 编码 Mircorsoft.JScript.GlobalObject.u ...

  9. docker学习-运行第一个docker镜像hello world

    docker pull  [OPTIONS] NAME[:TAG]:从远程仓库拉取一个镜像到本地,NAME是要拉取的镜像的名称,TAG是docker镜像的版本,不指定的话默认是最新版本 docker ...

  10. java基础---->多线程之yield(三)

    yield方法的作用是放弃当前的CPU资源,将它让给其它的任务去占用CPU执行时间.但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片.今天我们通过实例来学习一下yield()方法的使用.最是 ...