一、先看下什么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. JAVA_Package

    Javaの名前空間の仕組みの1つにパッケージがあります.大規模開発では必須の概念です.また.他人の作ったコードの再利用という観点でも.パッケージを正しく活用する必要があります. ・完全修飾名:パッケー ...

  2. 尚硅谷redis学习11-jedis操作redis

    前面学习了redis的知识后,下面学习一下如何在java中通过jedis操作redis. 所需jar包:commons-pool-xxxx.jar,jedis-xxx.jar 下面看一下常用操作: 1 ...

  3. Ftp命令使用

    FTP> ? 显示 ftp 命令说明.? 与 help 相同. 格式:?  [command] 说明:[command] 指定需要帮助的命令名称.如果没有指定 command,ftp将显示全部命 ...

  4. unity 向量赋值 传引用?传值?

    unity中,Vector2.Vector3之间的任意赋值都是传值 Vector2 v1; ,); v1=v2; v2.x=; Debug.Log(v1);//output: (2.0, 2.0) D ...

  5. Object-c @property与@synthesize的配对使用。

    功能:让编译器自动编写一个与数据成员同名的方法声明来省去读写方法的声明. 如: 1.在头文件中: @property int count; 等效于在头文件中声明2个方法: - (int)count; ...

  6. Examples: How to Pronounce T

    Examples: How to Pronounce T Share Tweet Share Tagged With: Flap T, Stop T The [t] sound is not alwa ...

  7. 趣味编程:静夜思(Swift版)

    func verticalWriting(txt:String, offset:Int) { Dictionary(grouping: txt.enumerated(), by: {$0.0 % of ...

  8. vmware搭建lnmp环境配置域名

    找到nginx配置文件,修改server_name 然后找到/etc/hosts文件 修改成如下 之后在Windows本地的C盘的hosts文件中添加解析 好了,这样就可以访问了 通往牛逼的路上,在意 ...

  9. Android 深入浅出 - 进程生命周期(Process Lifecycle)

    Android 5 个进程等级 1. Foreground Process : 2 .Visible Process : 3. Service Process : 4. Background Proc ...

  10. JAVAWEB 一一 Spirng(AOP面向切面)

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <!-- < ...