stark组件之pop操作【模仿Django的admin】
一、先看下什么django的admin的pop到底是个什么东西
其实就是这么一个东西,
a、在添加页面,在一对多和多对多的项后加了一个+号
b、点击这个加号,会弹出对应的添加 页面,在新的添加
c、添加完成后,新打开的页面自动关闭,然后把新添加数据的添加到对应的框中



二、下面我们来实现pop功能
a、知识点1,实现点击按钮,弹出一个新的窗口这个功能
首先我们写一个如下的html文件,点击这个文件,会重新打开一个窗口
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="button" value="button"> <script src="/static/jq/jquery-3.3.1.js"></script>
<script>
$("input").bind("click",function () {
{# window.open实现弹出一个新的窗口,然后打开我们对应的的url#}
window.open("/test_add/",'','width=400px,height=400px,top=100px,left=200px')
}) function bar(args) {
console.log(args)
}
</script>
</body>
</html>
效果如下

点击后的效果

添加窗口的html代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post">
{% csrf_token %}
书籍名称:<input type="text" name="name">
<input type="submit" value="submit"> </form>
</body>
</html>
然后我们看下这个form表单对应的视图函数
from app1 import models
def test_add(request):
if request.method == "POST":
name = request.POST.get("name")
models.test.objects.create(
name = name
) return render(request,"pop.html",{'name':name}) else:
return render(request,"test_add.html")
这里的代码我们要分析一下了、

这里为什么返回一个页面呢? 其实主要实现的效果就是添加成功,返回pop这个html文件,然后在pop的html文件中,我们会直接关闭窗口,另外我们这里进行了传参,主要是为了把当前添加的数据渲染到之前我们点击添加按钮的页面上
下面我们看下pop的html的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="/static/jq/jquery-3.3.1.js"></script> <script> {# 打开当前这个窗口对象#}
window.opener.bar('{{ name }}') {# 实现关闭页面的效果#}
window.close()
</script>
</body>
</html>
这里的代码还是需要解释一下,
这个是执行打开这个窗口的那个对象中的bar函数

这个是关闭当前的页面

我们最后看下bar函数,这样我们就可以实现在子页面和父页面之间进行数据传递的效果了

三、最后我们在我们的stark组件中实现pop功能
1、首先我们需要在每个input标签后面加一个“+”号
{% for field in form_obj %}
<div style="position: relative">
<label>{{ field.label }}</label>:
{{ field }}
<span class="pull-right">{{ field.errors.0 }}</span>
{# {% if field.pop %}#}
<a href="#" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>
{# {% endif %}#}
</div>
{% endfor %}
页面的效果如下

2、下面我们要判断,不能在所有的input标签后面弄一个加号,必须是一对多,或者多对多的才加,我们首先看下前端渲染的form_obj的类型是什么
def add_url(self,request):
model_name = self.model._meta.model_name
app_name = self.model._meta.app_label
# print(model_name,app_name,"============================")
print(self.model)
form_obj = self.get_model_form_class()
form_obj = form_obj()
print("form_obj",form_obj,type(form_obj))
from django.forms.boundfield import BoundField
from django.forms.models import ModelMultipleChoiceField
from django.forms.models import ModelChoiceField
if request.method == "GET":
for i in form_obj:
# if isinstance(i.field,(ModelMultipleChoiceField,ModelChoiceField)):
# i.pop = True
print(i,type(i),sep="-------------")
return render(request,"add_view.html",locals())
else:
form_obj = form_obj(request.POST)
if form_obj.is_valid():
form_obj.save()
path = "/stark/{app}/{model}".format(app=app_name,model=model_name)
return redirect(path) return render(request,"add_view.html",locals())

输出如下

我们看到所有的字段的类型都是一个类型,我们导入这个类看下这个类有什么方法
from django.forms.boundfield import BoundField

我们试着打印这个filed的属性的值和type
from django.forms.boundfield import BoundField
from django.forms.models import ModelMultipleChoiceField
from django.forms.models import ModelChoiceField
if request.method == "GET":
for i in form_obj:
# if isinstance(i.field,(ModelMultipleChoiceField,ModelChoiceField)):
# i.pop = True
print(type(i.field),sep="-------------")
return render(request,"add_view.html",locals())

结果如下

这里我们可以判断,如果字段是ModelMultipleChoiceField和ModelChoiceField的实例对象,则才加 加号
我们这里这样做,如果是ModelMultipleChoiceField和ModelChoiceField的实例对象,我们为这个实例对象赋值一个属性pop = true,然后我们在前端渲染的时候,判断有有个属性,则加 一个加号
后端的代码如下
model_name = self.model._meta.model_name
app_name = self.model._meta.app_label
# print(model_name,app_name,"============================")
print(self.model)
form_obj = self.get_model_form_class()
form_obj = form_obj()
print("form_obj",form_obj,type(form_obj))
from django.forms.boundfield import BoundField
from django.forms.models import ModelMultipleChoiceField
from django.forms.models import ModelChoiceField
if request.method == "GET":
for i in form_obj:
if isinstance(i.field,(ModelMultipleChoiceField,ModelChoiceField)):
i.pop = True
print(type(i.field),sep="-------------")

前端的代码如下
<div class="col-md-4 col-lg-offset-4" >
{% for field in form_obj %}
<div style="position: relative">
<label>{{ field.label }}</label>:
{{ field }}
<span class="pull-right">{{ field.errors.0 }}</span>
{% if field.pop %}
<a href="#" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>
{% endif %}
</div>
{% endfor %}
</div>
页面效果如下

2、下面我们实现点击加号弹出对应的框
首先我们为a标签绑定一个单机的事件,点击这个按钮执行pop函数
{% if field.pop %}
{# <a onclick="pop('{{ field.url }}')" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>#}
<a onclick="pop()" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>
{% endif %}

我们下面看下pop函数
function pop() {
alert(123)
}
点击按钮,看到我们的函数已经绑定上了

下面我们就是要实现点击按钮打开一个窗口的效果,首先我们需要拿到每个字段的的url
if request.method == "GET":
for i in form_obj:
if isinstance(i.field,(ModelMultipleChoiceField,ModelChoiceField)):
i.pop = True
print(dir(i.field.queryset.model),dir(i.field.queryset.model._meta),sep="-------------")
args1 = i.field.queryset.model._meta.model_name
args2 = i.field.queryset.model._meta.app_label
_url = "/stark/{args2}/{args1}/add".format(args1=args1,args2=args2)
i.url = _url return render(request,"add_view.html",locals())
先判断是否为一对多或者多对多,然后调用方法获取跨表的app的名称和表的名称

然后拼接url,然后为这个字段赋值一个url的属性

然后最后在html文件中接收一个url的参数
{% for field in form_obj %}
<div style="position: relative">
<label>{{ field.label }}</label>:
{{ field }}
<span class="pull-right">{{ field.errors.0 }}</span>
{% if field.pop %}
<a onclick="pop('{{ field.url }}')" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>
{# <a onclick="pop()" style="position: absolute;right: -30px;top: 30px"><span style="font-size: 20px">[+]</span></a>#}
{% endif %}
</div>

最后我们看下pop函数
function pop(url) {
window.open(url,"","")
}
最后我们看下页面的效果

至此,这一部分我们已经讲解完了
3、最后我们在实现这个功能,在弹出的新增的窗口添加新的数据,然后新添加的数据被添加到select标签中,且被选中的状态
首先我们要为每个点击加号点开的窗口添加一个url的参数,用来判断我这次添加的是哪张表的内容
if request.method == "GET":
form_obj = form_obj()
for i in form_obj:
if isinstance(i.field,(ModelMultipleChoiceField,ModelChoiceField)):
i.pop = True
args1 = i.field.queryset.model._meta.model_name
args2 = i.field.queryset.model._meta.app_label
_url = "/stark/{args2}/{args1}/add".format(args1=args1,args2=args2)
i.url = _url + "?pop_res_id=" + "id_" + args1 return render(request,"add_view.html",locals())

然后我们测试点击加号弹出的窗口的url


get方式处理完成,下面我们看下post的请求的处理
首先判断一下GET的参数中是否有pop_res_id这个变量,如果有的话,则走我们的pop处理的流程,如果没有的话,则走正常的添加的流程
model_form_obj = form_obj(request.POST)
if model_form_obj.is_valid():
res = model_form_obj.save()
pop_res_id = request.GET.get("pop_res_id",None) if pop_res_id:
pop_dict = {"pk":res.id,"text_name":str(res),"field":pop_res_id}
return render(request,"test_pop.html",{"pop_dict":pop_dict})
else: path = "/stark/{app}/{model}".format(app=app_name,model=model_name)
return redirect(path) return render(request,"add_view.html",locals())

如果走pop的添加流程,则需要借助一个save函数的返回值,因为我们后面要添加标签,所以这3个参数是必不可少的

然后我们在看下pop的html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="/static/jq/jquery-3.3.1.js"></script> <script> {# 打开当前这个窗口对象#}
window.opener.bar('{{ pop_dict.field }}','{{ pop_dict.pk }}',"{{ pop_dict.text_name }}"); {# 实现关闭页面的效果#}
window.close()
</script>
</body>
</html>

在看添加页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="/static/css/bootstrap.min.css"> <style>
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;
}
</style>
</head>
<body>
<h4>编辑页面</h4>
{% include "form.html" %} <script src="/static/jq/jquery-3.3.1.js"></script>
<script>
function bar(field,pk,text_name) {
var $option = $('<option>');
$option.html(text_name);
$option.val(pk);
$option.attr("selected","selected");
$("#" + field).append($option)
}
</script>
</body>
</html>
根据参数,创建option标签,且让他处于选中的状态

最后我们看下页面的效果

页面会实现自动选中的效果

至此pop的功能我们已经全部实现,还是比较复杂的
stark组件之pop操作【模仿Django的admin】的更多相关文章
- stark组件之批量操作【模仿Django的admin】
一.先看下django的admin是如何实现批量操作 首先在配置类中定义一个函数 然后我们为这个函数对象设置一个属性,这个属性主要用来显示在select标签中显示的文本内容 最后把函数对象放到一个ac ...
- stark组件之注册【模仿Django的admin】
一.先看下django的admin是如何实现注册功能 首先导入admin这个对象和我们的model模块 from django.contrib import admin # Register your ...
- stark组件之搜索【模仿Django的admin】
一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...
- stark组件之启动【模仿Django的admin】
首先需要在settings注册app INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib ...
- stark组件之分页【模仿Django的admin】
我们的stark组件用的我们的分页组件,没有重新写 下面直接看下分页的代码 class page_helper(): def __init__(self, count, current_page, p ...
- stark组件之路由分发【模仿Django的admin】
一.先看下django的admin是如何进行路由分发的 1.先看下django的admin的url路径有哪些 其实很简单,假如有一个书籍表,那么每张表对应四个url,增.删.改.查 查看的url ht ...
- stark组件之过滤操作【模仿Django的admin】
一.先看下django的admin是如何实现过滤操作 首先在配置类中顶一个list_filter的列表,把要过滤的字段作为元素写i进去就可以了 class testbook(admin.ModelAd ...
- stark组件之pop页面,按钮,url,页面
1.Window open() 方法 2.admin的pop添加按钮 3.stark之pop功能 3.知识点总结 4.coding代码 1.Window open() 方法 效果图 2.adm ...
- 12 stark组件之pop,按钮,url,页面
1.Window open() 方法 http://www.runoob.com/jsref/met-win-open.html 效果图 2.admin的pop添加按钮 3.stark之pop功能 ...
随机推荐
- jquery查找筛选器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- World Cup 996B(排队模拟)
题意:有n个通道,按顺序每一次站一个通道,直到所站的通道没有人 分析:模拟这个过程 #include<cstdio> int main() { ]; while(~scanf(" ...
- PRC远程过程调用
RPC(Remote Promote Call) 一种进程间通信方式.允许像调用本地服务一样调用远程服务. RPC框架的主要目标就是让远程服务调用更简单.透明.RPC框架负责屏蔽底层的传输方式(TCP ...
- 对String值不可变的理解以及String类型的引用传递问题
今天复习java时,突然注意到了一句以前没有注意过的一句话,String 是final修饰的,其值是不可变的.当时看的一脸懵逼,String str = "abc"; str = ...
- python 学习笔记之@property
今天学习python类看到 @property 的用法觉得很新奇,就自己尝试了很久,刚开始不明白,后来终于明白了点 其实总结一句话就是, @property 把类中的方法调用方式改变成当成属性属性调用 ...
- 【369】列表/字典的分拆, unpacking
参考: python--参数列表的分拆 参考: List Comprehensions 当你要传递的参数已经是一个列表,调用的函数却接受分开一个个的参数,这个时候可以考虑参数列表拆分: 可以使用* 操 ...
- .NET 基础知识
.net程序基本编写.执行流程(c#) 1>编写c#代码,保存为.cs文件. 2>通过csc.exe程序来将.cs文件编译为.net程序集(.exe或.dll).此 ...
- HashMap 实现总结
Entry类中需包含键值的hash值,防止resize时的重复计算: Map容量为2的整幂,可使用位操作取代取余操作提高效率: resize时需要将原table的桶内数据置null,利于垃圾回收: h ...
- gitbash上使用tree
gitbash上使用tree vscode从cmd设置gitbash之后,想在使用windows下的tree命令发现运行不了,有两种解决方案. 1,在gitbash上cmd //c tree,就等同c ...
- 使用arguments对象验证函数的参数是否合法
<script>function sum(arg1,arg2) //加法函数{ var realArgCount = arguments.length; //调用函数时传递的实参个数 va ...