一、先看下什么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】的更多相关文章

  1. stark组件之批量操作【模仿Django的admin】

    一.先看下django的admin是如何实现批量操作 首先在配置类中定义一个函数 然后我们为这个函数对象设置一个属性,这个属性主要用来显示在select标签中显示的文本内容 最后把函数对象放到一个ac ...

  2. stark组件之注册【模仿Django的admin】

    一.先看下django的admin是如何实现注册功能 首先导入admin这个对象和我们的model模块 from django.contrib import admin # Register your ...

  3. stark组件之搜索【模仿Django的admin】

    一.先看下django的admin是如何做搜索功能的 配置一个search_fields的列表就可以实现搜索的功能 class testbook(admin.ModelAdmin): # 第一步,定义 ...

  4. stark组件之启动【模仿Django的admin】

    首先需要在settings注册app INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib ...

  5. stark组件之分页【模仿Django的admin】

    我们的stark组件用的我们的分页组件,没有重新写 下面直接看下分页的代码 class page_helper(): def __init__(self, count, current_page, p ...

  6. stark组件之路由分发【模仿Django的admin】

    一.先看下django的admin是如何进行路由分发的 1.先看下django的admin的url路径有哪些 其实很简单,假如有一个书籍表,那么每张表对应四个url,增.删.改.查 查看的url ht ...

  7. stark组件之过滤操作【模仿Django的admin】

    一.先看下django的admin是如何实现过滤操作 首先在配置类中顶一个list_filter的列表,把要过滤的字段作为元素写i进去就可以了 class testbook(admin.ModelAd ...

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

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

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

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

随机推荐

  1. springboot 停止

    因springboot内嵌tomcat或jetty使得我们没法去操作服务: 因此,常常是服务起来后,要重启时会端口占用,我们只能无情的kill掉端口. 不过spring也设置有配置停止的请求: App ...

  2. CSS GRID ESSENTIALS

    CSS GRID ESSENTIALS Review At this point, we've covered a great deal of different ways to manipulate ...

  3. List根据时间字符串排序

    Collections.sort(resList, new Comparator<LoanApplyLogRes>() { @Override public int compare(Loa ...

  4. ReactiveX 学习笔记(19)使用 RxSwift + RxCocoa 进行 GUI 编程

    课题 程序界面由3个文本编辑框和1个文本标签组成. 要求文本标签实时显示3个文本编辑框所输入的数字之和. 文本编辑框输入的不是合法数字时,将其值视为0. 3个文本编辑框的初值分别为1,2,3. 创建工 ...

  5. avalon2学习教程05属性操作

    avalon2与avalon1的属性操作虽然都是使用ms-attr,但用法完全不一样. avalon1是这样操作属性的 其语法为 ms-attr-valueName="vmProp" ...

  6. SQL Server 数据库中的几个常见的临界值

    本文出处:http://www.cnblogs.com/wy123/p/6709520.html 1,SQL语句或者存储过程的最大长度(SQL字符串容量)是多少? 经常有人问,我的SQL语句是拼凑出来 ...

  7. Java Script 基础总结

    1学习ajax需要一点CSS的基础和JavaScipt基础 今天重温一下Javascrpt基础 1.<script type="text/javascript">< ...

  8. python批量操作Linux服务器脚本,key登录(执行命令、上传、下载)(二)

       -*-   2 #批量操作linux服务器(执行命令,上传,下载)   3 #!/usr/bin/python   4 import paramiko   5 import datetime   ...

  9. php预定义字符

    Php中预定义字符的处理: 1,htmlspecialchars()把一些预定义的字符转换为 HTML 实体. 函数原型:htmlspecialchars(string,quotestyle,char ...

  10. JS----文档对象模型

    DOM: document object model 文档对象模型提供了一套可以访问和修改HTML文档内容的方法 访问:获取 修改:设置 1 JS要去操作HTML元素,必须要先用JS找到他,转换为JS ...