一、先看下什么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. UI5-学习篇-7-Postman测试SAP OData Services

    1.Postman简介 用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具. postman ...

  2. python 可迭代对象与迭代器

    生成器函数的工作原理只要 Python 函数的定义体中有 yield 关键字, 该函数就是生成器函数. 调用生成器函数时, 会返回一个生成器对象. 也就是说, 生成器函数是生成器工厂. 调用生成器函数 ...

  3. 谈USB重定向的方式

    在桌面虚拟化的项目中,常常会遇到用户提出的各自外设需求,这时产品对外设的兼容性就成为了项目成败的拦路虎 本文试图用通俗易懂的语言讲讲USB外设重定向的工作流程,先看看普通PC上USB设备的工作流程 u ...

  4. 1037B--Reach Median(中位数)

    median 中位数 odd 奇数 even 奇数 You are given an array aa of nn integers and an integer ss. It is guarante ...

  5. RESET MASTER和RESET SLAVE使用场景和说明,以及清除主从同步关系

    mysql主从复制中,需要将从库提升为主库,需要取消其从库角色,这可通过执行RESET SLAVE ALL清除从库的同步复制信息.包括连接信息和二进制文件名.位置.从库上执行这个命令后,使用show ...

  6. linux 内核中一个全局变量引发的性能问题

    为了调试一个功能,在一个内核模块中,增加了一个全局变量,用来统计自有skb池的申请情况. 因为是临时增加,所以没有考虑性能,一开始只是一个fail的统计,数量不多,也不太考虑是否有计数丢失的情况,毕竟 ...

  7. jenkins+docker+docker-compose完整发版流程

    首先搭建jenkins+maven+nexus这一套自动化打包工具,并配置好相应配置,这里就不再赘述了. 其次,搭建好docker集群和私有仓库,以及安装好docker-compose工具,配置好相应 ...

  8. 一: Introduction(介绍)

    Welcome to SQLBackupRestore.com, your online resource for SQL Server backup and recovery issues.  Th ...

  9. FMS Dev Guide学习笔记(远程共享对象)

    一.开发交互式的媒体应用程序1.共享对象(Shared objects)    ----远程共享对象 在你创建一个远程共享对象之前,创建一个NetConnection对象并且连接到服务器.一旦你创建了 ...

  10. 如何使用CBO,CBO与RULE的区别

    Oracle的优化器有两种优化方式,即基于规则的优化方式(Rule-Based Optimization,简称为RBO)和基于代价的优化方式(Cost-Based Optimization,简称为CB ...