精华内容
下载资源
问答
  • jQuery拖动自定义创建表单代码是一款通过拖拽点击右侧表单项到空白区域来创建表单样式。
  • 简单账户创建表单网页模板
  • 在本章中,我们将学习如何使用 Bootstrap 创建表单。Bootstrap 通过一些简单的 HTML 标签和扩展的类即可创建出不同样式的表单
  • 山涧小河用户创建表单网页模板
  • 数字账户创建表单响应式网页模板
  • 主要介绍了Yii2创建表单(ActiveForm)的方法,结合实例形式详细分析了Yii创建表单的详细步骤及相关函数与属性的使用技巧,需要的朋友可以参考下
  • 在Vuejs中轻松创建表单
  • PHP创建表单

    千次阅读 2019-03-31 21:29:48
    创建表单,需要数据源,运算过程,以及输出结果,我们将它分为三层,并且对应数据源,运算过程,以及输出结果,以某表单为例; 一 创建数据源, 创建名为data.php为数据源 二 第二层为运算过程,这一层是最...

    准备工作

    创建表单,需要数据源,运算过程,以及输出结果,我们将它分为三层,并且对应数据源,运算过程,以及输出结果,以某表单为例;
    在这里插入图片描述

    创建数据源,
    在这里插入图片描述

    在这里插入图片描述
    创建名为data.php为数据源

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述
    第二层为运算过程,这一层是最重要的

    在这里插入图片描述
    最后一层为输出结果
    是最为简单的

    展开全文
  • 主要介绍了angular学习之动态创建表单的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • yii2 创建表单 笔记

    2016-04-18 10:43:52
    yii2 创建表单 笔记
  • 本文将介绍如何动态创建表单组件,我们最终实现的效果如下: 在阅读本文之前,请确保你已经掌握 Angular 响应式表单和动态创建组件的相关知识,如果对相关知识还不了解,推荐先阅读一下 Angular 4.x Reactive Forms...
  • jQuery bootstrap自定义创建表单工具代码
  • WinForm 自动创建表单

    2009-04-17 12:39:42
    自己实现的一个自动创建表单控件,包含控件源码和 示例源码。 用此控件需要为属性TableModel赋值,详细见示例。 根据数据库的数据类型,长度,创建表单(不支持二进制类型)。并可以把数据保存到数据库(添加、...
  • 在本章中,我们将学习如何使用 Bootstrap 创建表单。Bootstrap 通过一些简单的 HTML 标签和扩展的类即可创建出不同样式的表单,对bootstrap 表单相关知识感兴趣的朋友一起学习吧
  • java server face动态创建表单控件实例
  • SwiftyFORM, 用于创建表单的iOS框架 SwiftyFORM SwiftyFORM是一个用于创建表单的iOS框架。 因为表单代码很难写,难以阅读,难以理解。 在时间上a 。 维护起来很痛苦。在YouTube上的 SwiftyFORM演示开发发生
  • jQuery formBuilder,一个jQuery插件,能够通过拖放的方式创建表单
  • jQuery动态创建表单并提交

    千次阅读 2016-08-25 10:46:32
    jQuery动态创建表单并提交
    $("button").click(function(){
            action = "http://www.baidu.com";
            form = $("<form></form>")
            form.attr('action',action)
            form.attr('method','post')
            input1 = $("<input type='hidden' name='input1' />")
            input1.attr('value','input1 value')
            input2 = $("<input type='text' name='textinput' value='text input' />")
            form.append(input1)
            form.append(input2)
            form.appendTo("body")
            form.css('display','none')
            form.submit()
        })

    展开全文
  • 在上一节自定义表单环境搭建好以后,我就正式开始尝试自己创建表单,在后台的处理就比较常规,主要是针对ueditor插件的功能在前端进行修改。 由于自己的前端相关技术太渣,因此好多东西都不会用,导致修改实现的...

    注:环境配置:activiti自定义流程之自定义表单(一):环境配置

     

    在上一节自定义表单环境搭建好以后,我就正式开始尝试自己创建表单,在后台的处理就比较常规,主要是针对ueditor插件的功能在前端进行修改。


    由于自己的前端相关技术太渣,因此好多东西都不会用,导致修改实现的过程也是破费了一番功夫,头皮发麻了好几天。

    既然是用别人的插件进行修改,那么我想如果只是单独的贴出我修改后的代码,可能没有前后进行对比好理解,因此这里就把原代码和修改后的同时对比着贴出,以便于朋友们能从对比中更快的得到启发。

    一、首先是前台创建表单,原文件示例是所有代码直接都写在了index.html文件中,文件在文章最后:

     

     

    我在修改的过程中感觉这个代码太长,貌似有点杂乱,因此就自作主张的把部分内容提取到了新建的js文件中,还有部分我觉得无关紧要的东西也进行了删除,然后我的index.html代码如下:

     

     

     

    <!DOCTYPE HTML>
    <html>
     <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <link href="css/bootstrap/css/bootstrap.css?2023" rel="stylesheet" type="text/css" />
        <link href="css/site.css?2023" rel="stylesheet" type="text/css" />
        <link href="my_css/a.css" rel="stylesheet" type="text/css" />
        <script type="text/javascript">
            var _root='http://form/index.php?s=/',_controller = 'index';
        </script> 
     </head>
    <body style="margin:0">
    <!-- fixed navbar -->
    <!-- Docs page layout -->
    <div style="width:100%;height:60px;background-color:#ccf;border:1px solid blue;text-decoration:none">
         <img src="images/activiti.png" style="width:20%;height:98%;overflow:hidden;float:left"/>
         <ul style="margin-left:30px;margin-top:10px; padding: 0px; font-size: 30px; width:60%;overflow:hidden;float:left">
            <li><a href="#" onclick="toAdd();">新增表单</a></li>
            <li> | </li>
            <li><a href="#" onclick="formList();">表单列表</a></li>
         </ul>
    </div>
    <div id="idv1" style="width:100%;position: absolute;height:auto">
    <div style="width:70px;height:550px;position:relative;float:left;border:1px solid blue;background-color:#ccf">
      
    </div>
    <div id="formDiv" style="width:89%;height:auto;position:relative;float:left;margin-left:10px;margin-top:10px;">
    
    
    <div class="container">
    <form method="post" id="saveform" name="saveform" action="/index.php?s=/index/parse.html">
    <input type="hidden" name="fields" id="fields" value="0">
    <div style="width:98%;height:510px;margin-top:20px;border:3px solid grey">
      <p style="margin-top:10px;font-size:30px" >表单名称:<input type="text" id="formType"></input></p>
      <hr style="height:5px;border:none;border-top:5px ridge green;"/>
      <p style="margin-top:10px;font-size:30px" >表单设计:</p>
     <div >
    <p style="left:30px">
            <button type="button" onclick="leipiFormDesign.exec('text');" class="btn btn-info">文本框</button>
            <button type="button" onclick="leipiFormDesign.exec('textarea');" class="btn btn-info">多行文本</button>
            <button type="button" onclick="leipiFormDesign.exec('select');" class="btn btn-info">下拉菜单</button>
            <button type="button" onclick="leipiFormDesign.exec('radios');" class="btn btn-info">单选框</button>
            <button type="button" onclick="leipiFormDesign.exec('checkboxs');" class="btn btn-info">复选框</button>       
            <button type="button" onclick="leipiFormDesign.exec('listctrl');" class="btn btn-info">列表控件</button>
           <!--   <button type="button" onclick="leipiFormDesign.findForm();" class="btn btn-info">form</button>-->
    </p>
    
    
    </div>
    <!-- afsddddddddd -->
    <div >
    <script id="myFormDesign" type="text/plain" style="width:99.8%;">
    </script>
    </div>   
    </div>
    <!-- afsddddddddd -->
    <div class="row">
    
    
    </div><!--end row-->
    </form>
    </div><!--end container-->
    <script type="text/javascript" charset="utf-8" src="js/jquery-1.7.2.min.js?2023"></script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/ueditor.config.js?2023"></script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/ueditor.all.js?2023"> </script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/lang/zh-cn/zh-cn.js?2023"></script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/formdesign/leipi.formdesign.v4.js?2023"></script>
    <!-- script start-->  
    <script type="text/javascript" charset="utf-8" src="my_js/addForm.js"></script>
    <!-- script end -->
    <div style="width:1px;height:1px">
      <script type="text/javascript">
      var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
      document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F1e6fd3a46a5046661159c6bf55aad1cf' type='text/javascript'%3E%3C/script%3E"));
      </script>
    </div>
    
    
    </div>
    </div>
    </body>
    </html>
    

     

    相关的js文件命名为addForm.js如下:

     

     

    function toAdd(){
    	window.location.href="./"; 
    };
    function formList(){
    	window.location.href="my_views/formList.html"; 
    };
    
    
    var leipiEditor = UE.getEditor('myFormDesign',{
                toolleipi:true,//是否显示,设计器的 toolbars
                textarea: 'design_content',   
                //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个
               toolbars:[[
                ]],
                //关闭字数统计
                wordCount:false,
                //关闭elementPath
                elementPathEnabled:false,
                //默认的编辑区域高度
                initialFrameHeight:300
                //,iframeCssUrl:"css/bootstrap/css/bootstrap.css" //引入自身 css使编辑器兼容你网站css
                //更多其他参数,请参考ueditor.config.js中的配置项
            });
    
    
     var leipiFormDesign = {
    	findForm : function(){
    		window.location.href="my_views/formList.html";
    	},
        /*执行控件*/
        exec : function (method) {
            leipiEditor.execCommand(method);
        },
        /*
            Javascript 解析表单
            template 表单设计器里的Html内容
            fields 字段总数
        */
       parse_form:function(template,fields)
        {
            //正则  radios|checkboxs|select 匹配的边界 |--|  因为当使用 {} 时js报错
            var preg =  /(\|-<span(((?!<span).)*leipiplugins=\"(radios|checkboxs|select)\".*?)>(.*?)<\/span>-\||<(img|input|textarea|select).*?(<\/select>|<\/textarea>|\/>))/gi,preg_attr =/(\w+)=\"(.?|.+?)\"/gi,preg_group =/<input.*?\/>/gi;
            if(!fields) fields = 0;
            var template_parse = template,template_data = new Array(),add_fields=new Object(),checkboxs=0;
            var pno = 0;
            template.replace(preg, function(plugin,p1,p2,p3,p4,p5,p6){
                var parse_attr = new Array(),attr_arr_all = new Object(),name = '', select_dot = '' , is_new=false;
                var p0 = plugin;
                var tag = p6 ? p6 : p4;
                //alert(tag + " \n- t1 - "+p1 +" \n-2- " +p2+" \n-3- " +p3+" \n-4- " +p4+" \n-5- " +p5+" \n-6- " +p6);
                if(tag == 'radios' || tag == 'checkboxs')
                {
                    plugin = p2;
                }else if(tag == 'select')
                {
                    plugin = plugin.replace('|-','');
                    plugin = plugin.replace('-|','');
                }
                plugin.replace(preg_attr, function(str0,attr,val) {
                        if(attr=='name')
                        {
                            if(val=='leipiNewField')
                            {
                                is_new=true;
                                fields++;
                                val = 'data_'+fields;
                            }
                            name = val;
                        }
                        
                        if(tag=='select' && attr=='value')
                        {
                            if(!attr_arr_all[attr]) attr_arr_all[attr] = '';
                            attr_arr_all[attr] += select_dot + val;
                            select_dot = ',';
                        }else
                        {
                            attr_arr_all[attr] = val;
                        }
                        var oField = new Object();
                        oField[attr] = val;
                        parse_attr.push(oField);
                }) 
                /*alert(JSON.stringify(parse_attr));return;*/
                 if(tag =='checkboxs') /*复选组  多个字段 */
                 {
                    plugin = p0;
                    plugin = plugin.replace('|-','');
                    plugin = plugin.replace('-|','');
                    var name = 'checkboxs_'+checkboxs;
                    attr_arr_all['parse_name'] = name;
                    attr_arr_all['name'] = '';
                    attr_arr_all['value'] = '';
                    
                    attr_arr_all['content'] = '<span leipiplugins="checkboxs"  title="'+attr_arr_all['title']+'">';
                    var dot_name ='', dot_value = '';
                    p5.replace(preg_group, function(parse_group) {
                        var is_new=false,option = new Object();
                        parse_group.replace(preg_attr, function(str0,k,val) {
                            if(k=='name')
                            {
                                if(val=='leipiNewField')
                                {
                                    is_new=true;
                                    fields++;
                                    val = 'data_'+fields;
                                }
    
    
                                attr_arr_all['name'] += dot_name + val;
                                dot_name = ',';
    
    
                            }
                            else if(k=='value')
                            {
                                attr_arr_all['value'] += dot_value + val;
                                dot_value = ',';
    
    
                            }
                            option[k] = val;    
                        });
                        
                        if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
                        attr_arr_all['options'].push(option);
                        //if(!option['checked']) option['checked'] = '';
                        var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
                        attr_arr_all['content'] +='<input type="checkbox" name="'+option['name']+'" value="'+option['value']+'"  '+checked+'/>'+option['value']+' ';
    
    
                        if(is_new)
                        {
                            var arr = new Object();
                            arr['name'] = option['name'];
                            arr['leipiplugins'] = attr_arr_all['leipiplugins'];
                            add_fields[option['name']] = arr;
                        }
                    });
                    attr_arr_all['content'] += '</span>';
    
    
                    //parse
                    template = template.replace(plugin,attr_arr_all['content']);
                    template_parse = template_parse.replace(plugin,'{'+name+'}');
                    template_parse = template_parse.replace('{|-','');
                    template_parse = template_parse.replace('-|}','');
                    template_data[pno] = attr_arr_all;
                    checkboxs++;
    
    
                 }else if(name)
                {
                    if(tag =='radios') /*单选组  一个字段*/
                    {
                        plugin = p0;
                        plugin = plugin.replace('|-','');
                        plugin = plugin.replace('-|','');
                        attr_arr_all['value'] = '';
                        attr_arr_all['content'] = '<span leipiplugins="radios" name="'+attr_arr_all['name']+'" title="'+attr_arr_all['title']+'">';
                        var dot='';
                        p5.replace(preg_group, function(parse_group) {
                            var option = new Object();
                            parse_group.replace(preg_attr, function(str0,k,val) {
                                if(k=='value')
                                {
                                    attr_arr_all['value'] += dot + val;
                                    dot = ',';
                                }
                                option[k] = val;    
                            });
                            option['name'] = attr_arr_all['name'];
                            if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
                            attr_arr_all['options'].push(option);
                            //if(!option['checked']) option['checked'] = '';
                            var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
                            attr_arr_all['content'] +='<input type="radio" name="'+attr_arr_all['name']+'" value="'+option['value']+'"  '+checked+'/>'+option['value']+' ';
    
    
                        });
                        attr_arr_all['content'] += '</span>';
    
    
                    }else
                    {
                        attr_arr_all['content'] = is_new ? plugin.replace(/leipiNewField/,name) : plugin;
                    }
                    template = template.replace(plugin,attr_arr_all['content']);
                    template_parse = template_parse.replace(plugin,'{'+name+'}');
                    template_parse = template_parse.replace('{|-','');
                    template_parse = template_parse.replace('-|}','');
                    if(is_new)
                    {
                        var arr = new Object();
                        arr['name'] = name;
                        arr['leipiplugins'] = attr_arr_all['leipiplugins'];
                        add_fields[arr['name']] = arr;
                    }
                    template_data[pno] = attr_arr_all;   
                }
                pno++;
            })
            var parse_form = new Object({
                'fields':fields,//总字段数
                'template':template,//完整html
                'parse':template_parse,//控件替换为{data_1}的html
                'data':template_data,//控件属性
                'add_fields':add_fields//新增控件
            });
            return JSON.stringify(parse_form);
        },
        /*type  =  save 保存设计 versions 保存版本  close关闭 */
        fnCheckForm : function ( type ) {
        	var formType=document.getElementById("formType").value;
            if(leipiEditor.queryCommandState( 'source' ))
                leipiEditor.execCommand('source');//切换到编辑模式才提交,否则有bug   
            if(leipiEditor.hasContents()){
                leipiEditor.sync();/*同步内容*/
                //--------------以下仅参考-----------------------------------------------------------------------------------------------------
                var type_value='',formid=0,fields=$("#fields").val(),formeditor='';
    
    
                if( typeof type!=='undefined' ){
                    type_value = type;
                }
                console.log(document.getElementById("formType"));
                //获取表单设计器里的内容
                formeditor=leipiEditor.getContent();
                //解析表单设计器控件
                var parse_form = this.parse_form(formeditor,fields);
                 //异步提交数据
                 $.ajax({
                    type: 'POST',
                    url : '/webFormTest/addForm.do',
                    dataType : 'html',
                    async:false,
                    //contentType: 'application/json;charset=utf-8',
                    data : {'type' : type_value,'formid':formid,'parse_form':parse_form,"formType":formType},      
                    success : function(data){
                    	alert("保存成功");
                    	window.location.href ="./my_views/formList.html";
                    }
                });
                
            } else {
                alert('表单内容不能为空!')
                $('#submitbtn').button('reset');
                return false;
            }
        } ,
        /*预览表单*/
        fnReview : function (){
            if(leipiEditor.queryCommandState( 'source' ))
                leipiEditor.execCommand('source');/*切换到编辑模式才提交,否则部分浏览器有bug*/
            if(leipiEditor.hasContents()){
                leipiEditor.sync();       /*同步内容*/
                //--------------以下仅参考-------------------------------------------------------------------
                /*设计form的target 然后提交至一个新的窗口进行预览*/
                var type_value='',formid=0,fields=$("#fields").val(),formeditor='';
                var formType=document.getElementById("formType").value;
                if( typeof type!=='undefined' ){
                    type_value = type;
                }
                //获取表单设计器里的内容
                formeditor=leipiEditor.getContent();
                //解析表单设计器控件
                var parse_form = this.parse_form(formeditor,fields);
                var forms=JSON.parse(parse_form);
                console.log(forms);
                console.log(typeof forms);
                console.log(forms.template);
                var forms1=forms.template;
                	win_parse=window.open('','','width=800,height=400,alwaysRaised=yes,top=100,left=200');
                	//win_parse=window.open('','mywin',"menubar=0,toolbar=0,status=0,resizable=1,left=0,top=0,scrollbars=1,width=" +(screen.availWidth-10) + ",height=" + (screen.availHeight-50) + "\"");
                	var str='<div style="width:500px;height:300px;border:1px solid grey">'+forms1+'</div>';
                    win_parse.document.write(forms1);
                    win_parse.focus();     
            } else {
                alert('表单内容不能为空!');
                return false;
            }
        }
    };


    那么这里需要着重说明的就是js文件,在原文件中大家可以看到js也是写在html中的,最重要的是到了保存和预览的时候,都变了请用户自已处理:
    alert("你点击了保存,这里可以异步提交,请自行处理....");
    alert("你点击了预览,请自行处理....");

    于是我在对插件封装的数据进行了一定分析后就自行解决了这两个问题,也就是主要修改的地方。


    二、前台表单创建、预览完毕,要能实现以后都随时调用的功能,自然就需要存储到数据库中,前台似乎也能直接操作数据库,但是我本身是做后台的,因此就直接用了后台和数据库交互。

    后太也分别创建了model实体类、控制层controller、接口service、接口实现类serviceImp。因为这次主要是实现前台功能,我就把重心放在了前台,所以后台没有dao层。
    原本我是连service都不准备建立的,只是后来为了测试方便,还是建立了,因此各层看起来其实很混乱,该写在service的代码写在了controller,依次类推。
    代码分别如下:


    (1)、controller层,对前台传入的字符串进行了一定处理:

     

    package formControllers;
    import java.util.Map;
    import javax.servlet.http.HttpServletRequest;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import services.FormService;
    
    
    @Controller
    public class FormController {
    	@Autowired
    	FormService formService;
    
    
    	@RequestMapping(value = "/addForm.do", method = RequestMethod.POST)
    	@ResponseBody
    	public Object addForm(HttpServletRequest request) {
    		// String type_value = request.getParameter("type_value");
    		// String formid = request.getParameter("formid");
    		String parse_form = request.getParameter("parse_form");
    		String formType = request.getParameter("formType");
    		System.out.println(formType);
    		int index1 = parse_form.indexOf("\"template\":");
    		int index2 = parse_form.indexOf("\"parse\":");
    		String string = parse_form.substring(index1 + 12, index2 - 6);
    		string = string.replace("\\", "");
    		string = string.replace("{", "");
    		string = string.replace("}", "");
    		string = string.replace("|", "");
    		string = string.replace("-", "");
    		formService.addForm(formType, string);
    		return string;
    	}
    }
    

     

     

    (2)、service层存入数据库:

     

     

     

    Service:
    package services;
    import java.util.Map;
    
    
    public interface FormService {
    	public Object addForm(String formType, String string);
    }

     


    serviceImp代码:

     

     

    package servicesImp;
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import org.springframework.stereotype.Service;
    import services.FormService;
    @Service("FormService")
    public class FormServiceImp implements FormService {
    
    
    	/**
    	 * 新增表单
    	 * 
    	 * @author:tuzongxun
    	 * @Title: addForm
    	 * @Description: TODO
    	 * @param @param formType
    	 * @param @param string
    	 * @param @return
    	 * @date Mar 28, 2016 4:30:18 PM
    	 * @throws
    	 */
    	public Object addForm(String formType, String string) {
    		System.out.println(string);
    		try {
    			Connection connection = this.getDb();
    			PreparedStatement ps = connection
    					.prepareStatement("insert into  formtest(formId,formType,form) values(?,?,?)");
    			String formId = new Date().getTime() + "";
    			ps.setString(1, formId);
    			ps.setString(2, formType);
    			ps.setString(3, string);
    			ps.executeUpdate();
    			connection.close();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return string;
    	}
    
    
    	public Connection getDb() {
    		Connection connection = null;
    		try {
    			Class.forName("com.mysql.jdbc.Driver");
    			connection = DriverManager.getConnection(
    					"jdbc:mysql://localhost:3306/formtest", "root", "123456");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return connection;
    	}
    /**链接数据库*/<p align="left"><strong><span style="color:#7F0055;">public</span></strong> Connection getDb() {</p><p align="left">       Connection <span style="color:#6A3E3E;">connection</span> = <strong><span style="color:#7F0055;">null</span></strong>;</p><p align="left">       <strong><span style="color:#7F0055;">try</span></strong> {</p><p align="left">           Class.<em>forName</em>(<span style="color:#2A00FF;">"com.mysql.jdbc.Driver"</span>);</p><p align="left">           <span style="color:#6A3E3E;">connection</span> = DriverManager.<em>getConnection</em>(</p><p align="left">                  <span style="color:#2A00FF;">"jdbc:mysql://localhost:3306/formtest"</span>, <span style="color:#2A00FF;">"root"</span>, <span style="color:#2A00FF;">"123456"</span>);</p><p align="left">       } <strong><span style="color:#7F0055;">catch</span></strong> (Exception <span style="color:#6A3E3E;">e</span>) {</p><p align="left">           <span style="color:#6A3E3E;">e</span>.printStackTrace();</p><p align="left">       }</p><p align="left">       <strong><span style="color:#7F0055;">return</span></strong> <span style="color:#6A3E3E;">connection</span>;</p><p align="left">    }</p><p align="left"> }</p>

     

     

     


    Model实体:

     

     

     

     

     

    package models;
    public class FormModel {
    	// 'type' : type_value,'formid':formid,'parse_form':parse_form
    	private String formId;
    	private String type;
    	private Integer formid;
    	private String parse_form;
    	private String formType;
    
    
    	public String getType() {
    		return type;
    	}
    
    
    	public void setType(String type) {
    		this.type = type;
    	}
    
    
    	public int getFormid() {
    		return formid;
    	}
    
    
    	public String getParse_form() {
    		return parse_form;
    	}
    
    
    	public void setFormid(Integer formid) {
    		this.formid = formid;
    	}
    
    
    	public void setParse_form(String parse_form) {
    		this.parse_form = parse_form;
    	}
    
    
    	public String getFormType() {
    		return formType;
    	}
    
    
    	public void setFormType(String formType) {
    		this.formType = formType;
    	}
    
    
    	public String getFormId() {
    		return formId;
    	}
    
    
    	public void setFormId(String formId) {
    		this.formId = formId;
    	}
    
    
    	@Override
    	public String toString() {
    		return "FormModel [formId=" + formId + ", type=" + type + ", formid="
    				+ formid + ", parse_form=" + parse_form + ", formType="
    				+ formType + "]";
    	}
    
    
    }

     

    页面效果如图:

     

     

     

    原文index.html文件代码:

     

    <!DOCTYPE HTML>
    <html>
     <head>
        
        <title>WEB表单设计器 Ueditor Formdesign Plugins -leipi.org</title>
            <meta name="keyword" content="ueditor Formdesign plugins,formdesigner,ueditor扩展,web表单设计器,高级表单设计器,Leipi Form Design,web form设计器,web form designer,javascript jquery ueditor php表单设计器,formbuilder">
            <meta name="description" content="Ueditor Web Formdesign Plugins 扩展即WEB表单设计器扩展,它通常在、OA系统、问卷调查系统、考试系统、等领域发挥着重要作用,你可以在此基础上任意修改使功能无限强大!">
    
    
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="author" content="leipi.org">
        <link href="css/bootstrap/css/bootstrap.css?2023" rel="stylesheet" type="text/css" />
        <!--[if lte IE 6]>
        <link rel="stylesheet" type="text/css" href="css/bootstrap/css/bootstrap-ie6.css?2023">
        <![endif]-->
        <!--[if lte IE 7]>
        <link rel="stylesheet" type="text/css" href="css/bootstrap/css/ie.css?2023">
        <![endif]-->
        <link href="css/site.css?2023" rel="stylesheet" type="text/css" />
        <script type="text/javascript">
            var _root='http://form/index.php?s=/',_controller = 'index';
        </script>
        
    <!--style>
        .list-group-item{padding:0px;}
    </style-->
    
    
     </head>
    <body>
    
    
    <!-- fixed navbar -->
    <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="navbar-inner">
        <div class="container">
          <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="brand" href="http://www.leipi.org" target="_blank">雷劈网</a>
          <div class="nav-collapse collapse">
            <ul class="nav">
                <li class="active"><a href="/">表单设计器</a></li>
                <li ><a href="http://formdesign.leipi.org/doc.html">文档</a></li>
                <li ><a href="http://formdesign.leipi.org/demo.html">实例</a></li>
                <li ><a href="http://formdesign.leipi.org/downloads.html">下载</a></li>
                <li ><a href="http://formdesign.leipi.org/feedback.html">公开讨论</a></li>
            </ul>
          </div>
        </div>
      </div>
    </div>
    
    
    
    
        
    
    
    
    
    <!-- Docs page layout -->
    <div class="bs-header" id="content">
      <div class="container">
    
    
        <h1><img src="js/ueditor/formdesign/images/leipi_formdesign.png" width="64"/>WEB表单设计器 <small>Ueditor1.4.2 + Formdesign4.1.x</small></h1>
        <p>
            感谢大家使用,如有任何意见或建议,请务必告知,<a href="#bs-footer">免责声明</a>。
            <p>
            复制分享:<input type="text" value="大家都在用雷劈网WEB表单设计器,你去官网看看 http://formdesign.leipi.org/" style="width:80%" onclick="this.select()"/>
            </p>
            交流Q群: 143263697
        </p>
        
      </div>
    </div>
    
    
    
    
    <div class="container">
    <form method="post" id="saveform" name="saveform" action="/index.php?s=/index/parse.html">
    <input type="hidden" name="fields" id="fields" value="0">
    <div class="row">
    
    
        <div class="well well-small">
    <span class="pull-right">
        <a href="http://formdesign.leipi.org/demo.html" class="btn btn-success btn-small">使用实例演示</a>
    </span>
    
    
    <p>
     一栏布局:<br /><br />
            <button type="button" onclick="leipiFormDesign.exec('text');" class="btn btn-info">文本框</button>
            <button type="button" onclick="leipiFormDesign.exec('textarea');" class="btn btn-info">多行文本</button>
            <button type="button" onclick="leipiFormDesign.exec('select');" class="btn btn-info">下拉菜单</button>
            <button type="button" onclick="leipiFormDesign.exec('radios');" class="btn btn-info">单选框</button>
            <button type="button" onclick="leipiFormDesign.exec('checkboxs');" class="btn btn-info">复选框</button>
            <button type="button" onclick="leipiFormDesign.exec('macros');" class="btn btn-info">宏控件</button>
            <button type="button" onclick="leipiFormDesign.exec('progressbar');" class="btn btn-info">进度条</button>
            <button type="button" onclick="leipiFormDesign.exec('qrcode');" class="btn btn-info">二维码</button>
            <button type="button" onclick="leipiFormDesign.exec('listctrl');" class="btn btn-info">列表控件</button>
            <button type="button" onclick="leipiFormDesign.exec('more');" class="btn btn-primary">一起参与...</button>
    </p>
         </div>
         
    </div>
    
    
    
    
    <div class="alert">
        <button type="button" class="close" data-dismiss="alert">×</button>
        <strong>提醒:</strong>单选框和复选框,如:<code>{|-</code>选项<code>-|}</code>两边边界是防止误删除控件,程序会把它们替换为空,请不要手动删除!
    </div>
    
    
    
    
    <div class="row">
    
    
    <div class="span2">
    <ul class="nav nav-list">
        <li class="nav-header">两栏布局</li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('text');" class="btn btn-link">文本框</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('textarea');" class="btn btn-link">多行文本</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('select');" class="btn btn-link">下拉菜单</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('radios');" class="btn btn-link">单选框</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('checkboxs');" class="btn btn-link">复选框</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('macros');" class="btn btn-link">宏控件</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('progressbar');" class="btn btn-link">进度条</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('qrcode');" class="btn btn-link">二维码</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('listctrl');" class="btn btn-link">列表控件</a></li>
        <li><a href="javascript:void(0);" onclick="leipiFormDesign.exec('more');" class="btn btn-link">一起参与...</a></li>
        
    </ul>
    
    
    </div>
    
    
    <div class="span10">
    
    
    <script id="myFormDesign" type="text/plain" style="width:100%;">
    <p style="text-align: center;">
        <br/>
    </p>
    <p style="text-align: center;">
        <span style="font-size: 24px;">示例表</span>
    </p>
    <table class="table table-bordered">
        <tbody>
            <tr class="firstRow">
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);">
                    文本框
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="227">
                    <input style="text-align: left; width: 150px;" title="文本框" value="雷劈网" name="leipiNewField" orgheight="" orgwidth="150" orgalign="left" orgfontsize="" orghide="0" leipiplugins="text" orgtype="text"/>
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="85">
                    下拉菜单
                </td>
                <td valign="top" style="border-color: rgb(221, 221, 221);" width="312">
                    {|-<span leipiplugins="select"><select name="leipiNewField" title="下拉菜单" leipiplugins="select" size="1" orgwidth="150" style="width: 150px;"><option value="下拉">
                        下拉
                    </option>
                    <option value="菜单">
                        菜单
                    </option></select>  </span>-|}
                </td>
            </tr>
            <tr>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);">
                    单选
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="41">
    {|-<span leipiplugins="radios"  title="单选" name="leipiNewField">
        <input  value="单选1"   type="radio" checked="checked"/>单选1 
        <input  value="单选2"  type="radio"/>单选2 
    </span>-|}
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="85">
                    复选
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="312">
                    {|-<span leipiplugins="checkboxs" title="复选">
                        <input name="leipiNewField" value="复选1"  type="checkbox" checked="checked"/>复选1 
                        <input name="leipiNewField" value="复选2"  type="checkbox" checked="checked"/>复选2 
                        <input name="leipiNewField" value="复选3"  type="checkbox"/>复选3 
                        </span>-|}
                </td>
            </tr>
            <tr>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);">
                    宏控件
                </td>
                <td valign="top" style="border-color: rgb(221, 221, 221);" width="41">
                    <input name="leipiNewField" type="text" value="{macros}" title="宏控件" leipiplugins="macros" orgtype="sys_date_cn" orghide="0" orgfontsize="12" orgwidth="150" style="font-size: 12px; width: 150px;"/>
                </td>
                <td valign="top" style="word-break: break-all; border-color: rgb(221, 221, 221);" width="85">
                    二维码
                </td>
                <td valign="top" style="border-color: rgb(221, 221, 221);" width="312">
                    <img name="leipiNewField" title="雷劈网" value="http://www.leipi.org" orgtype="url" leipiplugins="qrcode" src="js/ueditor/formdesign/images/qrcode.gif" orgwidth="40" orgheight="40" style="width: 40px; height: 40px;"/>
                </td>
            </tr>
        </tbody>
    </table>
    <p>
        <input name="leipiNewField" leipiplugins="listctrl" type="text" value="{列表控件}" readonly="readonly" title="采购商品列表" orgtitle="商品名称`数量`单价`小计`描述`" orgcoltype="text`int`int`int`text`" orgunit="```元``" orgsum="0`0`0`1`0`" orgcolvalue="`````" orgwidth="100%" style="width: 100%;"/>
    </p>
    <p>
        <textarea title="多行文本" name="leipiNewField" leipiplugins="textarea" value="" orgrich="0" orgfontsize="12" orgwidth="600" orgheight="80" style="font-size:12px;width:600px;height:80px;"></textarea>
    </p>
    <p>
        <img name="leipiNewField" title="进度条" leipiplugins="progressbar" orgvalue="20" orgsigntype="progress-info" src="js/ueditor/formdesign/images/progressbar.gif"/>
    </p>
    </script>
    </div>
    
    
    
    
    
    
    </div><!--end row-->
    
    
    </form>
    
    
    
    
    
    
    </div><!--end container-->
    
    
    
    
     
    
    
        
     <div class="bs-footer" role="contentinfo" id="bs-footer">
          <div class="container">
              <p><span class="glyphicon glyphicon-list-alt"></span> 免责声明:本站仅分享开发思路和示例代码并且乐于交流和促进网络良性发展,是非商业工具,如有疑问请加群或邮件告知,积极配合调整。</p>
              <p><span class="glyphicon glyphicon-list-alt"></span> 反馈:payonesmile@qq.com</p>
              <p><span class="glyphicon glyphicon-usd"></span> 支持:捐赠支付宝 payonesmile@qq.com 、<a href="#">捐赠记录</a></p>
              <p><span class="glyphicon glyphicon-bookmark"></span> 鸣谢:<a href="http://ueditor.baidu.com" target="_balnk">UEditor</a>、<a href="https://github.com/twbs/bootstrap/" target="_balnk">Bootstrap</a>、<a href="http://www.leipi.org" target="_balnk">雷劈网</a></p>
              <p><a href="http://www.leipi.org" title="雷劈网"><img src="http://www.leipi.org/wp-content/themes/leipi/images/leipi.png" alt="雷劈认证 icon" height="30"></a> &copy;2014 Ueditor Formdesign Plugins v4 leipi.org <a href="http://www.miitbeian.gov.cn/" target="_blank">粤ICP备13051130号</a></p>
          </div>
    </div>
        
    
    
    <script type="text/javascript" charset="utf-8" src="js/jquery-1.7.2.min.js?2023"></script>
    
    
    <script type="text/javascript" charset="utf-8" src="js/ueditor/ueditor.config.js?2023"></script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/ueditor.all.js?2023"> </script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/lang/zh-cn/zh-cn.js?2023"></script>
    <script type="text/javascript" charset="utf-8" src="js/ueditor/formdesign/leipi.formdesign.v4.js?2023"></script>
    <!-- script start-->  
    <script type="text/javascript">
    var leipiEditor = UE.getEditor('myFormDesign',{
                //allowDivTransToP: false,//阻止转换div 为p
                toolleipi:true,//是否显示,设计器的 toolbars
                textarea: 'design_content',   
                //这里可以选择自己需要的工具按钮名称,此处仅选择如下五个
               toolbars:[[
                'fullscreen', 'source', '|', 'undo', 'redo', '|','bold', 'italic', 'underline', 'fontborder', 'strikethrough',  'removeformat', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist','|', 'fontfamily', 'fontsize', '|', 'indent', '|', 'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|',  'link', 'unlink',  '|',  'horizontal',  'spechars',  'wordimage', '|', 'inserttable', 'deletetable',  'mergecells',  'splittocells']],
                //focus时自动清空初始化时的内容
                //autoClearinitialContent:true,
                //关闭字数统计
                wordCount:false,
                //关闭elementPath
                elementPathEnabled:false,
                //默认的编辑区域高度
                initialFrameHeight:300
                //,iframeCssUrl:"css/bootstrap/css/bootstrap.css" //引入自身 css使编辑器兼容你网站css
                //更多其他参数,请参考ueditor.config.js中的配置项
            });
    
    
     var leipiFormDesign = {
        /*执行控件*/
        exec : function (method) {
            leipiEditor.execCommand(method);
        },
        /*
            Javascript 解析表单
            template 表单设计器里的Html内容
            fields 字段总数
        */
       parse_form:function(template,fields)
        {
            //正则  radios|checkboxs|select 匹配的边界 |--|  因为当使用 {} 时js报错
            var preg =  /(\|-<span(((?!<span).)*leipiplugins=\"(radios|checkboxs|select)\".*?)>(.*?)<\/span>-\||<(img|input|textarea|select).*?(<\/select>|<\/textarea>|\/>))/gi,preg_attr =/(\w+)=\"(.?|.+?)\"/gi,preg_group =/<input.*?\/>/gi;
            if(!fields) fields = 0;
    
    
            var template_parse = template,template_data = new Array(),add_fields=new Object(),checkboxs=0;
    
    
            var pno = 0;
            template.replace(preg, function(plugin,p1,p2,p3,p4,p5,p6){
                var parse_attr = new Array(),attr_arr_all = new Object(),name = '', select_dot = '' , is_new=false;
                var p0 = plugin;
                var tag = p6 ? p6 : p4;
                //alert(tag + " \n- t1 - "+p1 +" \n-2- " +p2+" \n-3- " +p3+" \n-4- " +p4+" \n-5- " +p5+" \n-6- " +p6);
    
    
                if(tag == 'radios' || tag == 'checkboxs')
                {
                    plugin = p2;
                }else if(tag == 'select')
                {
                    plugin = plugin.replace('|-','');
                    plugin = plugin.replace('-|','');
                }
                plugin.replace(preg_attr, function(str0,attr,val) {
                        if(attr=='name')
                        {
                            if(val=='leipiNewField')
                            {
                                is_new=true;
                                fields++;
                                val = 'data_'+fields;
                            }
                            name = val;
                        }
                        
                        if(tag=='select' && attr=='value')
                        {
                            if(!attr_arr_all[attr]) attr_arr_all[attr] = '';
                            attr_arr_all[attr] += select_dot + val;
                            select_dot = ',';
                        }else
                        {
                            attr_arr_all[attr] = val;
                        }
                        var oField = new Object();
                        oField[attr] = val;
                        parse_attr.push(oField);
                }) 
                /*alert(JSON.stringify(parse_attr));return;*/
                 if(tag =='checkboxs') /*复选组  多个字段 */
                 {
                    plugin = p0;
                    plugin = plugin.replace('|-','');
                    plugin = plugin.replace('-|','');
                    var name = 'checkboxs_'+checkboxs;
                    attr_arr_all['parse_name'] = name;
                    attr_arr_all['name'] = '';
                    attr_arr_all['value'] = '';
                    
                    attr_arr_all['content'] = '<span leipiplugins="checkboxs"  title="'+attr_arr_all['title']+'">';
                    var dot_name ='', dot_value = '';
                    p5.replace(preg_group, function(parse_group) {
                        var is_new=false,option = new Object();
                        parse_group.replace(preg_attr, function(str0,k,val) {
                            if(k=='name')
                            {
                                if(val=='leipiNewField')
                                {
                                    is_new=true;
                                    fields++;
                                    val = 'data_'+fields;
                                }
    
    
                                attr_arr_all['name'] += dot_name + val;
                                dot_name = ',';
    
    
                            }
                            else if(k=='value')
                            {
                                attr_arr_all['value'] += dot_value + val;
                                dot_value = ',';
    
    
                            }
                            option[k] = val;    
                        });
                        
                        if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
                        attr_arr_all['options'].push(option);
                        //if(!option['checked']) option['checked'] = '';
                        var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
                        attr_arr_all['content'] +='<input type="checkbox" name="'+option['name']+'" value="'+option['value']+'"  '+checked+'/>'+option['value']+' ';
    
    
                        if(is_new)
                        {
                            var arr = new Object();
                            arr['name'] = option['name'];
                            arr['leipiplugins'] = attr_arr_all['leipiplugins'];
                            add_fields[option['name']] = arr;
    
    
                        }
    
    
                    });
                    attr_arr_all['content'] += '</span>';
    
    
                    //parse
                    template = template.replace(plugin,attr_arr_all['content']);
                    template_parse = template_parse.replace(plugin,'{'+name+'}');
                    template_parse = template_parse.replace('{|-','');
                    template_parse = template_parse.replace('-|}','');
                    template_data[pno] = attr_arr_all;
                    checkboxs++;
    
    
                 }else if(name)
                {
                    if(tag =='radios') /*单选组  一个字段*/
                    {
                        plugin = p0;
                        plugin = plugin.replace('|-','');
                        plugin = plugin.replace('-|','');
                        attr_arr_all['value'] = '';
                        attr_arr_all['content'] = '<span leipiplugins="radios" name="'+attr_arr_all['name']+'" title="'+attr_arr_all['title']+'">';
                        var dot='';
                        p5.replace(preg_group, function(parse_group) {
                            var option = new Object();
                            parse_group.replace(preg_attr, function(str0,k,val) {
                                if(k=='value')
                                {
                                    attr_arr_all['value'] += dot + val;
                                    dot = ',';
                                }
                                option[k] = val;    
                            });
                            option['name'] = attr_arr_all['name'];
                            if(!attr_arr_all['options']) attr_arr_all['options'] = new Array();
                            attr_arr_all['options'].push(option);
                            //if(!option['checked']) option['checked'] = '';
                            var checked = option['checked'] !=undefined ? 'checked="checked"' : '';
                            attr_arr_all['content'] +='<input type="radio" name="'+attr_arr_all['name']+'" value="'+option['value']+'"  '+checked+'/>'+option['value']+' ';
    
    
                        });
                        attr_arr_all['content'] += '</span>';
    
    
                    }else
                    {
                        attr_arr_all['content'] = is_new ? plugin.replace(/leipiNewField/,name) : plugin;
                    }
                    //attr_arr_all['itemid'] = fields;
                    //attr_arr_all['tag'] = tag;
                    template = template.replace(plugin,attr_arr_all['content']);
                    template_parse = template_parse.replace(plugin,'{'+name+'}');
                    template_parse = template_parse.replace('{|-','');
                    template_parse = template_parse.replace('-|}','');
                    if(is_new)
                    {
                        var arr = new Object();
                        arr['name'] = name;
                        arr['leipiplugins'] = attr_arr_all['leipiplugins'];
                        add_fields[arr['name']] = arr;
                    }
                    template_data[pno] = attr_arr_all;
    
    
                   
                }
                pno++;
            })
            var parse_form = new Object({
                'fields':fields,//总字段数
                'template':template,//完整html
                'parse':template_parse,//控件替换为{data_1}的html
                'data':template_data,//控件属性
                'add_fields':add_fields//新增控件
            });
            return JSON.stringify(parse_form);
        },
        /*type  =  save 保存设计 versions 保存版本  close关闭 */
        fnCheckForm : function ( type ) {
            if(leipiEditor.queryCommandState( 'source' ))
                leipiEditor.execCommand('source');//切换到编辑模式才提交,否则有bug
                
            if(leipiEditor.hasContents()){
                leipiEditor.sync();/*同步内容*/
                
                alert("你点击了保存,这里可以异步提交,请自行处理....");
                return false;
                //--------------以下仅参考-----------------------------------------------------------------------------------------------------
                var type_value='',formid=0,fields=$("#fields").val(),formeditor='';
    
    
                if( typeof type!=='undefined' ){
                    type_value = type;
                }
                //获取表单设计器里的内容
                formeditor=leipiEditor.getContent();
                //解析表单设计器控件
                var parse_form = this.parse_form(formeditor,fields);
                //alert(parse_form);
                
                 //异步提交数据
                 $.ajax({
                    type: 'POST',
                    url : '/index.php?s=/index/parse.html',
                    //dataType : 'json',
                    data : {'type' : type_value,'formid':formid,'parse_form':parse_form},
                    success : function(data){
                        if(confirm('查看js解析后,提交到服务器的数据,请临时允许弹窗'))
                        {
                            win_parse=window.open('','','width=800,height=600');
                            //这里临时查看,所以替换一下,实际情况下不需要替换  
                            data  = data.replace(/<\/+textarea/,'<textarea');
                            win_parse.document.write('<textarea style="width:100%;height:100%">'+data+'</textarea>');
                            win_parse.focus();
                        }
                        
                        /*
                      if(data.success==1){
                          alert('保存成功');
                          $('#submitbtn').button('reset');
                      }else{
                          alert('保存失败!');
                      }*/
                    }
                });
                
            } else {
                alert('表单内容不能为空!')
                $('#submitbtn').button('reset');
                return false;
            }
        } ,
        /*预览表单*/
        fnReview : function (){
            if(leipiEditor.queryCommandState( 'source' ))
                leipiEditor.execCommand('source');/*切换到编辑模式才提交,否则部分浏览器有bug*/
                
            if(leipiEditor.hasContents()){
                leipiEditor.sync();       /*同步内容*/
                
                 alert("你点击了预览,请自行处理....");
                return false;
                //--------------以下仅参考-------------------------------------------------------------------
    
    
    
    
                /*设计form的target 然后提交至一个新的窗口进行预览*/
                document.saveform.target="mywin";
                window.open('','mywin',"menubar=0,toolbar=0,status=0,resizable=1,left=0,top=0,scrollbars=1,width=" +(screen.availWidth-10) + ",height=" + (screen.availHeight-50) + "\"");
    
    
                document.saveform.action="/index.php?s=/index/preview.html";
                document.saveform.submit(); //提交表单
            } else {
                alert('表单内容不能为空!');
                return false;
            }
        }
    };
    
    
    </script>
    <!-- script end -->
    
    
    
    
    <!-这个div已经被我删除-
    <div style="display: none;">                                                                   
    88888888888  88                             ad88  88                ad88888ba   8888888888   
    88           ""                            d8"    88               d8"     "88  88           
    88                                         88     88               8P       88  88  ____     
    88aaaaa      88  8b,dPPYba,   ,adPPYba,  MM88MMM  88  8b       d8  Y8,    ,d88  88a8PPPP8b,  
    88"""""      88  88P'   "Y8  a8P_____88    88     88  `8b     d8'   "PPPPPP"88  PP"     `8b  
    88           88  88          8PP"""""""    88     88   `8b   d8'            8P           d8  
    88           88  88          "8b,   ,aa    88     88    `8b,d8'    8b,    a8P   Y8a     a8P  
    88           88  88           `"Ybbd8"'    88     88      Y88'     `"Y8888P'     "Y88888P"   
                                                              d8'                                
    2014-3-15 Firefly95、Ard、xinG、Xiaoyaodaya               d8'  
    </div>
    <div style="width:1px;height:1px">
      <script type="text/javascript">
      var _bdhmProtocol = (("https:" == document.location.protocol) ? " https://" : " http://");
      document.write(unescape("%3Cscript src='" + _bdhmProtocol + "hm.baidu.com/h.js%3F1e6fd3a46a5046661159c6bf55aad1cf' type='text/javascript'%3E%3C/script%3E"));
      </script>
    </div>
    </body>
    </html>
    

     

     

     

     

     

    展开全文
  • 从模型创建表单ModelForm

    千次阅读 2017-11-02 09:06:11
    从模型创建表单 ModelForm¶ class ModelForm¶ 如果你正在构建一个数据库驱动的应用,那么你应该会有与Django 的模型紧密映射的表单。举个例子,你也许会有个BlogComment 模型,并且你还想创建一个...

    从模型创建表单

    ModelForm

    class  ModelForm

    如果你正在构建一个数据库驱动的应用,那么你应该会有与Django 的模型紧密映射的表单。举个例子,你也许会有个BlogComment 模型,并且你还想创建一个表单让大家提交评论到这个模型中。 在这种情况下,在表单中定义字段将是冗余的,因为你已经在模型中定义了字段。

    基于这个原因,Django 提供一个辅助类来让你可以从Django 的模型创建表单

    例如:

    >>> from django.forms import ModelForm
    >>> from myapp.models import Article
    
    # Create the form class.
    >>> class ArticleForm(ModelForm):
    ...     class Meta:
    ...         model = Article
    ...         fields = ['pub_date', 'headline', 'content', 'reporter']
    
    # Creating a form to add an article.
    >>> form = ArticleForm()
    
    # Creating a form to change an existing article.
    >>> article = Article.objects.get(pk=1)
    >>> form = ArticleForm(instance=article)
    

    字段类型

    生成的表单类中将具有和指定的模型字段对应的表单字段,顺序为fields 属性中指定的顺序。

    每个模型字段有一个对应的默认表单字段。比如,模型中的CharField 表现成表单中的CharField模型中的ManyToManyField 字段会表现成MultipleChoiceField 字段。下面是一个完整的列表:

    Model field Form field
    AutoFieldNot represented in the form
    BigIntegerFieldIntegerField with min_value set to -9223372036854775808 and max_valueset to 9223372036854775807.
    BooleanFieldBooleanField
    CharFieldCharField with max_length set to the model field’s max_length
    CommaSeparatedIntegerFieldCharField
    DateFieldDateField
    DateTimeFieldDateTimeField
    DecimalFieldDecimalField
    EmailFieldEmailField
    FileFieldFileField
    FilePathFieldFilePathField
    FloatFieldFloatField
    ForeignKeyModelChoiceField (see below)
    ImageFieldImageField
    IntegerFieldIntegerField
    IPAddressFieldIPAddressField
    GenericIPAddressFieldGenericIPAddressField
    ManyToManyFieldModelMultipleChoiceField (see below)
    NullBooleanFieldNullBooleanField
    PositiveIntegerFieldIntegerField
    PositiveSmallIntegerFieldIntegerField
    SlugFieldSlugField
    SmallIntegerFieldIntegerField
    TextFieldCharField with widget=forms.Textarea
    TimeFieldTimeField
    URLFieldURLField

    可能如你所料,ForeignKey 和 ManyToManyField 字段类型属于特殊情况:

    • ForeignKey 表示成django.forms.ModelChoiceField,它是一个ChoiceField,其选项是模型的查询集
    • ManyToManyField 表示成django.forms.ModelMultipleChoiceField,它是一个MultipleChoiceField,其选项是模型的查询集

    此外,生成的每个表单字段都有以下属性集:

    • 如果模型字段设置blank=True,那么表单字段的required 设置为False否则,required=True
    • 表单字段的label 设置为模型字段的verbose_name,并将第一个字母大写。
    • 表单字段的help_text 设置为模型字段的help_text
    • 如果模型字段设置了choices,那么表单字段的Widget 将设置成Select,其选项来自模型字段的choices选项通常会包含空选项,并且会默认选择。如果字段是必选的,它会强制用户选择一个选项。如果模型字段的blank=False 且具有一个显示的default值,将不会包含空选项(初始将选择default 值)。

    最后,请注意你可以为给定的模型字段重新指定表单字段。参见下文覆盖默认的字段

    一个完整的例子

    考虑下面的模型:

    from django.db import models
    from django.forms import ModelForm
    
    TITLE_CHOICES = (
        ('MR', 'Mr.'),
        ('MRS', 'Mrs.'),
        ('MS', 'Ms.'),
    )
    
    class Author(models.Model):
        name = models.CharField(max_length=100)
        title = models.CharField(max_length=3, choices=TITLE_CHOICES)
        birth_date = models.DateField(blank=True, null=True)
    
        def __str__(self):              # __unicode__ on Python 2
            return self.name
    
    class Book(models.Model):
        name = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author)
    
    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ['name', 'title', 'birth_date']
    
    class BookForm(ModelForm):
        class Meta:
            model = Book
            fields = ['name', 'authors']
    

    上面ModelForm 的子类大体等同于(唯一的不同是save() 方法,我们将稍后讨论):

    from django import forms
    
    class AuthorForm(forms.Form):
        name = forms.CharField(max_length=100)
        title = forms.CharField(max_length=3,
                    widget=forms.Select(choices=TITLE_CHOICES))
        birth_date = forms.DateField(required=False)
    
    class BookForm(forms.Form):
        name = forms.CharField(max_length=100)
        authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
    

    模型表单的验证

    验证模型表单主要有两步:

    1. 验证表单
    2. 验证模型实例

    与普通的表单验证类型类似,模型表单的验证在调用is_valid() 或访问errors 属性时隐式调用,或者通过full_clean() 显式调用,尽管在实际应用中你将很少使用后一种方法。

    模型的验证(Model.full_clean())在表单验证这一步的内部触发,紧跟在表单的clean() 方法调用之后。

    警告

    Clean 过程会以各种方式修改传递给模型表单构造函数的模型实例。例如,模型的日期字段将转换成日期对象。验证失败可能导致模型实例处于不一致的状态,所以不建议重新使用它。

    重写clean() 方法

    可以重写模型表单的clean() 来提供额外的验证,方法和普通的表单一样。

    模型表单实例包含一个instance 属性,表示与它绑定的模型实例。

    警告

    ModelForm.clean() 方法设置一个标识符, 使得模型验证 这一步验证标记为unique、 unique_together 或unique_for_date|month|year 的模型字段的唯一性。

    如果你需要覆盖clean() 方法并维持这个验证行为,你必须调用父类的clean() 方法。

    与模型验证的交互

    作为验证过程的一部分,模型表单将调用与表单字段对应的每个模型字段的clean() 方法。如果你已经排除某些模型字段,这些字段不会运行验证。关于字段clean 和验证是如何工作的,参见表单字段的文档。

    模型的clean() 方法在任何唯一性检查之前调用。关于模型clean() 钩子的更多信息,参见验证对象 。

    模型error_messages 的注意事项

    表单字段级别或表单级别的错误信息永远比模型字段级别的错误信息优先。

    模型字段的错误信息只用于模型验证步骤引发ValidationError 的时候,且不会有对应的表单级别的错误信息。

    New in Django 1.7.

    你可以根据模型验证引发的NON_FIELD_ERRORS 覆盖错误信息,方法是添加 NON_FIELD_ERRORS 键到模型表单内联Meta 类的error_messages 字典:

    from django.forms import ModelForm
    from django.core.exceptions import NON_FIELD_ERRORS
    
    class ArticleForm(ModelForm):
        class Meta:
            error_messages = {
                NON_FIELD_ERRORS: {
                    'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
                }
            }
    

    save() 方法

    每个ModelForm还具有一个save() 方法。这个方法根据表单绑定的数据创建并保存数据库对象。模型表单的子类可以用关键字参数instance 接收一个已经存在的模型实例;如果提供,save() 将更新这个实例。如果没有提供,save() 将创建模型的一个新实例:

    >>> from myapp.models import Article
    >>> from myapp.forms import ArticleForm
    
    # Create a form instance from POST data.
    >>> f = ArticleForm(request.POST)
    
    # Save a new Article object from the form's data.
    >>> new_article = f.save()
    
    # Create a form to edit an existing Article, but use
    # POST data to populate the form.
    >>> a = Article.objects.get(pk=1)
    >>> f = ArticleForm(request.POST, instance=a)
    >>> f.save()
    

    注意,如果表单没有验证save() 调用将通过检查form.errors 来进行验证。如果表单中的数据不合法,将引发ValueError —— 例如,如果form.errors 为True

    save() 接受一个可选的commit 关键字参数,其值为True 或False如果save() 时commit=False,那么它将返回一个还没有保存到数据库的对象。这种情况下,你需要调用返回的模型实例的save()。 如果你想在保存之前自定义一些处理,或者你想使用特定的模型保存选项,可以这样使用。commit 默认为True

    使用commit=False 的另外一个副作用是在模型具有多对多关系的时候。如果模型具有多对多关系而且当你保存表单时指定commit=False,Django 不会立即为多对多关系保存表单数据。这是因为只有实例在数据库中存在时才可以保存实例的多对多数据。

    为了解决这个问题,每当你使用commit=False 保存表单时,Django 将添加一个save_m2m() 方法到你的模型表单子类。在你手工保存由表单生成的实例之后,你可以调用save_m2m() 来保存多对多的表单数据。例如:

    # Create a form instance with POST data.
    >>> f = AuthorForm(request.POST)
    
    # Create, but don't save the new author instance.
    >>> new_author = f.save(commit=False)
    
    # Modify the author in some way.
    >>> new_author.some_field = 'some_value'
    
    # Save the new instance.
    >>> new_author.save()
    
    # Now, save the many-to-many data for the form.
    >>> f.save_m2m()
    

    save_m2m() 只在你使用save(commit=False) 时才需要。当你直接使用save(),所有的数据 —— 包括多对多数据 —— 都将保存而不需要任何额外的方法调用。例如:

    # Create a form instance with POST data.
    >>> a = Author()
    >>> f = AuthorForm(request.POST, instance=a)
    
    # Create and save the new author instance. There's no need to do anything else.
    >>> new_author = f.save()
    

    除了save() 和save_m2m() 方法之外,模型表单与其它表单的工作方式完全一样。例如,is_valid()用于检查合法性,is_multipart() 方法用于决定表单是否需要multipart 的文件上传(以及这之后request.FILES 是否必须必须传递给表单)等等。更多信息,参见绑定上传的文件到表单

    选择用到的字段

    强烈建议你使用fields 属性显式设置所有将要在表单中编辑的字段。如果不这样做,当表单不小心允许用户设置某些特定的字段,特别是有的字段添加到模型中的时候,将很容易导致安全问题。这些问题可能在网页上根本看不出来,它与表单的渲染方式有关。

    另外一种方式是自动包含所有的字段,或者排除某些字段。这种基本方式的安全性要差很多,而且已经导致大型的网站受到严重的利用(例如 GitHub)。

    然而,有两种简单的方法保证你不会出现这些安全问题:

    1. 设置fields 属性为特殊的值'__all__' 以表示需要使用模型的所有字段。例如:

      from django.forms import ModelForm
      
      class AuthorForm(ModelForm):
          class Meta:
              model = Author
              fields = '__all__'
      
    2. 设置ModelForm 内联的Meta 类的exclude 属性为一个要从表单中排除的字段的列表。

      例如:

      class PartialAuthorForm(ModelForm):
          class Meta:
              model = Author
              exclude = ['title']
      

      因为Author 模型有3个字段nametitle 和 birth_date,上面的例子会让name 和 birth_date 出现在表单中。

    如果使用上面两种方法,表单中字段出现的顺序将和字段在模型中定义的顺序一致,其中ManyToManyField 出现在最后。

    另外,Django 还将使用以下规则:如果设置模型字段的editable=False,那么使用ModelForm 从该模型创建的任何表单都不会包含该字段。

    Changed in Django 1.8:

    在旧的版本中,同时省略fields 和exclude 字段将导致模型的所有字段出现在表单中。现在这样做将引发一个ImproperlyConfigured 异常。

    不会被上述逻辑包含进表单中的字段将不会被表单的save() 方法保存。另外,如果你手工添加排除的字段到表单中,它们也不会从模型实例初始化。

    Django 将阻止保存不完全的模型,所以如果模型不允许缺失的字段为空且没有提供默认值,带有缺失字段的ModelForm 的save()将失败。为了避免这种失败,实例化模型时必须带有缺失的字段的初始值:

    author = Author(title='Mr')
    form = PartialAuthorForm(request.POST, instance=author)
    form.save()
    

    还有一种方法,你可以使用save(commit=False) 并手工设置额外需要的字段:

    form = PartialAuthorForm(request.POST)
    author = form.save(commit=False)
    author.title = 'Mr'
    author.save()
    

    关于使用save(commit=False) 的更多细节参见保存表单一节

    重写(覆盖)默认的字段

    上文字段类型表中默认的字段类型只是合理的默认值。如果你的模型中有一个DateField,你可能想在表单中也将它表示成DateField但是ModelForm 还提供更多的灵活性,让你可以改变给定的模型字段对应的表单字段的类型和Widget。

    使用内部类Meta 的widgets 属性可以指定一个字段的自定义Widget。它是映射字段名到Widget 类或实例的一个字典。

    例如,Author 的name 属性为CharField,如果你希望它表示成一个<textarea> 而不是默认的<input type="text">,你可以覆盖字段默认的Widget:

    from django.forms import ModelForm, Textarea
    from myapp.models import Author
    
    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ('name', 'title', 'birth_date')
            widgets = {
                'name': Textarea(attrs={'cols': 80, 'rows': 20}),
            }
    

    不管是Widget 实例(Textarea(...))还是Widget 类(Textarea),widgets 字典都可以接收。

    类似地,如果你希望进一步自定义字段,你可以指定内部类Meta 的labelshelp_texts 和error_messages

    例如,如果你希望自定义name 字段所有面向用户的字符串:

    from django.utils.translation import ugettext_lazy as _
    
    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ('name', 'title', 'birth_date')
            labels = {
                'name': _('Writer'),
            }
            help_texts = {
                'name': _('Some useful help text.'),
            }
            error_messages = {
                'name': {
                    'max_length': _("This writer's name is too long."),
                },
            }
    

    最后,如果你希望完全控制字段 —— 包括它的类型、验证器等等,你可以像在普通的表单那样显式指定字段。

    例如,如果你想为slug 字段使用MySlugFormField ,可以像下面这样:

    from django.forms import ModelForm
    from myapp.models import Article
    
    class ArticleForm(ModelForm):
        slug = MySlugFormField()
    
        class Meta:
            model = Article
            fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
    

    如果想要指定字段的验证器,可以显式定义字段并设置它的validators 参数:

    from django.forms import ModelForm, CharField
    from myapp.models import Article
    
    class ArticleForm(ModelForm):
        slug = CharField(validators=[validate_slug])
    
        class Meta:
            model = Article
            fields = ['pub_date', 'headline', 'content', 'reporter', 'slug']
    

    当你像这样显式实例化表单字段时,需要理解ModelForm 和普通的Form 的关系是怎样的。

    ModelForm就是可以自动生产相应字段的Form.自动生成哪些字段取决于Meta 类的fields属性和在该ModelForm中显示声明的字段。ModelForm 基本上 生成表单中没有的字段,换句话讲就是没有显式定义的字段。

    显式定义的字段会保持原样,所以Meta 属性中任何自定义的属性例如 widgetslabelshelp_textserror_messages 都将忽略;它们只适用于自动生成的字段。

    类似地,显式定义的字段不会从对应的模型中获取属性,例如 max_length 或required。 如果你希望保持模型中指定的行为,你必须设置在声明表单字段时显式设置相关的参数。

    例如,如果Article 模型像下面这样:

    class Article(models.Model):
        headline = models.CharField(max_length=200, null=True, blank=True,
                                    help_text="Use puns liberally")
        content = models.TextField()
    

    而你想为headline 做一些自定义的验证,在保持blank 和help_text 值的同时,你必须这样定义ArticleForm

    class ArticleForm(ModelForm):
        headline = MyFormField(max_length=200, required=False,
                               help_text="Use puns liberally")
    
        class Meta:
            model = Article
            fields = ['headline', 'content']
    

    你必须保证表单字段的类型可以用于对应的模型字段。如果它们不兼容,因为不会有显示的转换你将会得到一个ValueError

    关于字段和它们的参数,参见表单字段的文档

    启用字段的本地化功能

    默认情况下,ModelForm 中的字段不会本地化它们的数据。你可以使用Meta 类的localized_fields 属性来启用字段的本地化功能。

    >>> from django.forms import ModelForm
    >>> from myapp.models import Author
    >>> class AuthorForm(ModelForm):
    ...     class Meta:
    ...         model = Author
    ...         localized_fields = ('birth_date',)
    

    如果localized_fields 设置为'__all__' 这个特殊的值,所有的字段都将本地化。

    表单继承

    在基本的表单里,你可以通过继承ModelForms来扩展和重用他们。当你的form是通过models生成的,而且需要在父类的基础上声明额外的field和method,这种继承是方便的。例如,使用以前的ArticleForm 类:

    >>> class EnhancedArticleForm(ArticleForm):
    ...     def clean_pub_date(self):
    ...         ...
    

    以上创建了一个与 ArticleForm非常类似的form,除了一些额外的验证和pub_date 的cleaning

    你也可以在子类中继承父类的内部类 Meta来重写它的属性列表,比如 Meta.fields 或者Meta.excludes :

    >>> class RestrictedArticleForm(EnhancedArticleForm):
    ...     class Meta(ArticleForm.Meta):
    ...         exclude = ('body',)
    

    上例从父类EnhancedArticleForm继承后增加了额外的方法,并修改了 ArticleForm.Meta 排除了一个字段

    当然,有一些注意事项

    • 应用正常的Python名称解析规则。如果你有多个基类声明一个Meta内部类,只会使用第一个。这意味着孩子的Meta(如果存在),否则第一个父母的Meta等。
    Changed in Django 1.7.
    • 它可以同时继承FormModelForm,但是,必须确保ModelForm首先出现在MRO中。这是因为这些类依赖于不同的元类,而一个类只能有一个元类。
    New in Django 1.7.
    • 可以通过在子类上将名称设置为None,声明性地删除从父类继承的Field

      您只能使用此技术选择退出由父类声明定义的字段;它不会阻止ModelForm元类生成默认字段。要退出默认字段,请参阅Selecting the fields to use

    提供初始值

    作为一个有参数的表单, 在实例化一个表单时可以通过指定initial字段来指定表单中数据的初始值. 这种方式指定的初始值将会同时替换掉表单中的字段和值. 例如:

    >>> article = Article.objects.get(pk=1)
    >>> article.headline
    'My headline'
    >>> form = ArticleForm(initial={'headline': 'Initial headline'}, instance=article)
    >>> form['headline'].value()
    'Initial headline'
    

    模型表单的factory函数

    你可以用单独的函数 modelform_factory() 来代替使用类定义来从模型直接创建表单。这在不需要很多自定义的情况下应该是更方便的。

    >>> from django.forms.models import modelform_factory
    >>> from myapp.models import Book
    >>> BookForm = modelform_factory(Book, fields=("author", "title"))
    

    这个函数还能对已有的表单类做简单的修改,比如,对给出的字段指定 widgets :

    >>> from django.forms import Textarea
    >>> Form = modelform_factory(Book, form=BookForm,
    ...                          widgets={"title": Textarea()})
    

    表单包含的字段可以用 fieldsexclude关键字参数说明,或者用ModelForm内部Meta类的相应属性说明。请看 ModelForm文档: 选择使用的字段

    ... 或者为指定的字段启用本地化功能。

    >>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=("birth_date",))
    

    模型表单集

    class  models. BaseModelFormSet

    普通表单集一样, 它是Django提供的几个有力的表单集类来简化模型操作。让我们继续使用上面的Author模型:

    >>> from django.forms.models import modelformset_factory
    >>> from myapp.models import Author
    >>> AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
    

    使用 fields限定表单集仅可以使用给出的字段,或者使用排除法,指定哪些字段被不被使用。

    >>> AuthorFormSet = modelformset_factory(Author, exclude=('birth_date',))
    
    Changed in Django 1.8:

    在旧版本中,同时省略fields 和exclude 的结果是表单集使用模型的所有字段。现在这么做将引发ImproperlyConfigured 异常。

    下面将创建一个与Author 模型数据相关联的功能强大的表单集,与普通表单集运行一样:

    >>> formset = AuthorFormSet()
    >>> print(formset)
    <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" id="id_form-MAX_NUM_FORMS" />
    <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100" /></td></tr>
    <tr><th><label for="id_form-0-title">Title:</label></th><td><select name="form-0-title" id="id_form-0-title">
    <option value="" selected="selected">---------</option>
    <option value="MR">Mr.</option>
    <option value="MRS">Mrs.</option>
    <option value="MS">Ms.</option>
    </select><input type="hidden" name="form-0-id" id="id_form-0-id" /></td></tr>
    

    注意

    modelformset_factory()使用formset_factory() 生成表单集,这意味着模型表单集仅仅是扩展基本表单集,使其能处理模型的信息。

    更改查询集

    默认的, 如果你使用model生成formset,formset会使用一个包含模型全部对象的queryset(例如:Author.objects.all()). 你可以使用queryset参数重写这一行为:

    >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
    

    或者,你可以创建子类设置 self.queryset in __init__:

    from django.forms.models import BaseModelFormSet
    from myapp.models import Author
    
    class BaseAuthorFormSet(BaseModelFormSet):
        def __init__(self, *args, **kwargs):
            super(BaseAuthorFormSet, self).__init__(*args, **kwargs)
            self.queryset = Author.objects.filter(name__startswith='O')
    

    然后,将BaseAuthorFormSet 类传给modelformset_factory函数:

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, fields=('name', 'title'), formset=BaseAuthorFormSet)
    

    如果想返回不包含任何已存在模型实例的表单集,可以指定一个空的查询集(QuerySet):

    >>> AuthorFormSet(queryset=Author.objects.none())
    

    更改form

    默认情况下,当你使用modelformset_factory时, modelform_factory()将会创建一个模型 通常这有助于指定一个自定义模型表单. 例如,你可以创建一个自定义验证的表单模型

    class AuthorForm(forms.ModelForm):
        class Meta:
            model = Author
            fields = ('name', 'title')
    
        def clean_name(self):
            # custom validation for the name field
            ...
    

    然后,把你的模型作为参数传递过去

    AuthorFormSet = modelformset_factory(Author, form=AuthorForm)
    

    并不总是需要自定义一个模型表单, modelformset_factory 函数有几个参数,可以传给modelform_factory,他们的说明如下:

    指定要在widgets中使用的小部件

    使用widgets 参数,可以用字典值自定义ModelForm列出字段的widget类。这与 widgets字典在 ModelForm 的内部Meta类作用式一样。

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, fields=('name', 'title'),
    ...     widgets={'name': Textarea(attrs={'cols': 80, 'rows': 20})})
    

    使用localized_fields为字段启用本地化

    使用 localized_fields参数,可以使表单中字段启用本地化。

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, fields=('name', 'title', 'birth_date'),
    ...     localized_fields=('birth_date',))
    

    如果localized_fields设置值为 '__all__',将本地化所有字段。

    提供初始化数据

    与普通表单集一样,modelformset_factory()能返回初始化的模型表单集,initial参数能为表单集的中表单指定初始数据 。但是,在模型表单集中,初始数据仅应用在增加的表单中,不会应用到已存在的模型实例。如果用户没有更改新增加表单中的初始数据,那他们也不会被校验和保存。

    保存表单集中的对象

    做为 ModelForm, 你可以保存数据到模型对象,以下就完成了表单集的 save()方法:

    # Create a formset instance with POST data.
    >>> formset = AuthorFormSet(request.POST)
    
    # Assuming all is valid, save the data.
    >>> instances = formset.save()
    

    save()方法返回已保存到数据库的实例。如果给定实例的数据在绑定数据中没有更改,那么实例将不会保存到数据库,并且不会包含在返回值中(在上面的示例中为instances)。

    当窗体中缺少字段(例如因为它们已被排除)时,这些字段不会由save()方法设置。您可以在选择要使用的字段中找到有关此限制的更多信息,这也适用于常规ModelForms

    传递commit=False返回未保存的模型实例:

    # don't save to the database
    >>> instances = formset.save(commit=False)
    >>> for instance in instances:
    ...     # do something with instance
    ...     instance.save()
    

    这使您能够在将数据保存到数据库之前将数据附加到实例。如果您的表单集包含ManyToManyField,您还需要调用formset.save_m2m(),以确保多对多关系正确保存。

    调用save()之后,您的模型formset将有三个包含formset更改的新属性:

    models.BaseModelFormSet. changed_objects
    models.BaseModelFormSet. deleted_objects
    models.BaseModelFormSet. new_objects

    操作表单对像的数量限制

    与普通表单集一样,你可以用在modelformset_factory()中使用 max_num 和 extra 参数,来控制额外表单的显示数量。

    max_num 不会限制已经存在的表单对像的显示:

    >>> Author.objects.order_by('name')
    [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]
    
    >>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=1)
    >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
    >>> [x.name for x in formset.get_queryset()]
    ['Charles Baudelaire', 'Paul Verlaine', 'Walt Whitman']
    

    如果 max_num大于存在的关联对像的数量,表单集将添加 extra个额外的空白表单,只要表单总数量不超过 max_num

    >>> AuthorFormSet = modelformset_factory(Author, fields=('name',), max_num=4, extra=2)
    >>> formset = AuthorFormSet(queryset=Author.objects.order_by('name'))
    >>> for form in formset:
    ...     print(form.as_table())
    <tr><th><label for="id_form-0-name">Name:</label></th><td><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100" /><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></td></tr>
    <tr><th><label for="id_form-1-name">Name:</label></th><td><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100" /><input type="hidden" name="form-1-id" value="3" id="id_form-1-id" /></td></tr>
    <tr><th><label for="id_form-2-name">Name:</label></th><td><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100" /><input type="hidden" name="form-2-id" value="2" id="id_form-2-id" /></td></tr>
    <tr><th><label for="id_form-3-name">Name:</label></th><td><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100" /><input type="hidden" name="form-3-id" id="id_form-3-id" /></td></tr>
    

     max_num 值为f None (缺省)设置一个较高的限制可显示1000个表单。实际上相当于没有限制。

    在视图中使用模型表单集

    模型表单集与表单集十分类似,假设我们想要提供一个表单集来编辑Author模型实例:

    from django.forms.models import modelformset_factory
    from django.shortcuts import render_to_response
    from myapp.models import Author
    
    def manage_authors(request):
        AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
        if request.method == 'POST':
            formset = AuthorFormSet(request.POST, request.FILES)
            if formset.is_valid():
                formset.save()
                # do something.
        else:
            formset = AuthorFormSet()
        return render_to_response("manage_authors.html", {
            "formset": formset,
        })
    

    可以看到,模型表单集的视图逻辑与“正常”表单集的视图逻辑没有显着不同。唯一的区别是我们调用formset.save()将数据保存到数据库中。(上面已经描述了在保存窗体集中的对象。)

    ModelFormSet上覆盖clean()

    ModelForms一样,默认情况下,ModelFormSetclean()方法将验证formset中没有项目违反唯一约束(uniqueunique_togetherunique_for_date|month|year)。如果要覆盖ModelFormSet上的clean()方法并维护此验证,则必须调用父类的clean方法:

    from django.forms.models import BaseModelFormSet
    
    class MyModelFormSet(BaseModelFormSet):
        def clean(self):
            super(MyModelFormSet, self).clean()
            # example custom validation across forms in the formset
            for form in self.forms:
                # your custom formset validation
                ...
    

    另请注意,到达此步骤时,已为每个Form创建了各个模型实例。修改form.cleaned_data中的值不足以影响保存的值。如果您希望修改ModelFormSet.clean()中的值,则必须修改form.instance

    from django.forms.models import BaseModelFormSet
    
    class MyModelFormSet(BaseModelFormSet):
        def clean(self):
            super(MyModelFormSet, self).clean()
    
            for form in self.forms:
                name = form.cleaned_data['name'].upper()
                form.cleaned_data['name'] = name
                # update the instance value.
                form.instance.name = name
    

    使用自定义queryset

    如前所述,您可以覆盖模型formset使用的默认查询集:

    from django.forms.models import modelformset_factory
    from django.shortcuts import render_to_response
    from myapp.models import Author
    
    def manage_authors(request):
        AuthorFormSet = modelformset_factory(Author, fields=('name', 'title'))
        if request.method == "POST":
            formset = AuthorFormSet(request.POST, request.FILES,
                                    queryset=Author.objects.filter(name__startswith='O'))
            if formset.is_valid():
                formset.save()
                # Do something.
        else:
            formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith='O'))
        return render_to_response("manage_authors.html", {
            "formset": formset,
        })
    

    请注意,我们在此示例中的POSTGET中传递queryset参数。

    在模板中使用表单集

    在Django模板中有三种方式来渲染表单集。

    第一种方式,你可以让表单集完成大部分的工作

    <form method="post" action="">
        {{ formset }}
    </form>
    

    其次,你可以手动渲染formset,但让表单处理自己:

    <form method="post" action="">
        {{ formset.management_form }}
        {% for form in formset %}
            {{ form }}
        {% endfor %}
    </form>
    

    当您自己手动呈现表单时,请确保呈现如上所示的管理表单。请参阅management form documentation

    第三,您可以手动呈现每个字段:

    <form method="post" action="">
        {{ formset.management_form }}
        {% for form in formset %}
            {% for field in form %}
                {{ field.label_tag }} {{ field }}
            {% endfor %}
        {% endfor %}
    </form>
    

    如果您选择使用此第三种方法,并且不对{% for %} t0> loop,你需要渲染主键字段。例如,如果您要渲染模型的nameage字段:

    <form method="post" action="">
        {{ formset.management_form }}
        {% for form in formset %}
            {{ form.id }}
            <ul>
                <li>{{ form.name }}</li>
                <li>{{ form.age }}</li>
            </ul>
        {% endfor %}
    </form>
    

    注意我们需要如何显式渲染{{ form.id }}这确保了在POST情况下的模型形式集将正常工作。(此示例假设名为id的主键。如果您明确定义了自己的主键(不是id),请确保其呈现)。

    内联formets

    class  models. BaseInlineFormSet

    内联formets是模型formets上的一个小的抽象层。这些简化了通过外键处理相关对象的情况。假设你有这两个模型:

    from django.db import models
    
    class Author(models.Model):
        name = models.CharField(max_length=100)
    
    class Book(models.Model):
        author = models.ForeignKey(Author)
        title = models.CharField(max_length=100)
    

    如果要创建允许您编辑属于特定作者的图书的表单集,您可以执行以下操作:

    >>> from django.forms.models import inlineformset_factory
    >>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',))
    >>> author = Author.objects.get(name='Mike Royko')
    >>> formset = BookFormSet(instance=author)
    

    注意

    inlineformset_factory()使用modelformset_factory()并标记为can_delete=True

    覆盖InlineFormSet上的方法

    当覆盖InlineFormSet上的方法时,您应该子类化BaseInlineFormSet,而不是BaseModelFormSet

    例如,如果要覆盖clean()

    from django.forms.models import BaseInlineFormSet
    
    class CustomInlineFormSet(BaseInlineFormSet):
        def clean(self):
            super(CustomInlineFormSet, self).clean()
            # example custom validation across forms in the formset
            for form in self.forms:
                # your custom formset validation
                ...
    

    另请参见Overriding clean() on a ModelFormSet上的clean()。

    然后,在创建内联表单集时,传递可选参数formset

    >>> from django.forms.models import inlineformset_factory
    >>> BookFormSet = inlineformset_factory(Author, Book, fields=('title',),
    ...     formset=CustomInlineFormSet)
    >>> author = Author.objects.get(name='Mike Royko')
    >>> formset = BookFormSet(instance=author)
    

    多个外键对同一个模型

    如果您的模型在同一个模型中包含多个外键,则需要使用fk_name手动解决歧义。例如,考虑以下模型:

    class Friendship(models.Model):
        from_friend = models.ForeignKey(Friend, related_name='from_friends')
        to_friend = models.ForeignKey(Friend, related_name='friends')
        length_in_months = models.IntegerField()
    

    要解决此问题,您可以使用fk_nameinlineformset_factory()

    >>> FriendshipFormSet = inlineformset_factory(Friend, Friendship, fk_name='from_friend',
    ...     fields=('to_friend', 'length_in_months'))
    

    在视图中使用内联格式集

    您可能需要提供一个视图,允许用户编辑模型的相关对象。以下是如何做到这一点:

    def manage_books(request, author_id):
        author = Author.objects.get(pk=author_id)
        BookInlineFormSet = inlineformset_factory(Author, Book, fields=('title',))
        if request.method == "POST":
            formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
            if formset.is_valid():
                formset.save()
                # Do something. Should generally end with a redirect. For example:
                return HttpResponseRedirect(author.get_absolute_url())
        else:
            formset = BookInlineFormSet(instance=author)
        return render_to_response("manage_books.html", {
            "formset": formset,
        })
    

    注意我们如何在POSTGET例中传递instance

    指定要在内联表单中使用的窗口小部件

    inlineformset_factory使用modelformset_factory并将其大部分参数传递给modelformset_factory这意味着您可以使用widgets参数,将其传递到modelformset_factory请参阅上面的指定要在窗体中使用的窗口小部件的窗口小部件。

    展开全文
  • 上海电子信息职业技术学院 通信与信息工程学院软件技术系 网页制作课程任务单 姓 名 学 号 班级 成绩 学习情景编号 11 学习情景名称 在HTML文档中创建表单 学时 2 任务要求 在公司网站子页HTML文档中创建表单 训练...
  • 这是插件的一个简单程序包,使您可以使用带有Sage 10的相应...创建表单后,只需使用分配给表单的段生成一个视图: $ wp acorn make:form contact-us 您将在resources/views/forms/contact-us.blade.php中找到生成的
  • JS创建表单提交后台设置请求方式

    千次阅读 2016-08-19 11:39:34
    JS 创建表单并提交 用途:在界面上选择几千个订单,读取ID号提交到后台处理,有几种方法实现,$.ajax方法提交不能打开新窗口,form表单提交可能被其他功能占用。 创建表单并设置参数类型、提交方式等,可以实现 form...
  • 动态创建表单

    千次阅读 2018-02-07 09:08:21
    function deleteUser2(id){ var myform = document.createElement...//创建form节点 //添加action属性 myform.setAttribute("action", "${pageContext.request.contextPath}/userInfo/delete/"+id); myform.setAtt
  • 翻译自在JavaFX中创建表单 在开发应用程序时,创建表单是一项常见活动。本教程将向您介绍屏幕布局的基础知识,如何将控件添加到布局窗格以及如何创建输入事件。 在本教程中,您将使用JavaFX构建如图4-1所示的登录...
  • Flask创建表单

    千次阅读 2017-01-12 15:22:27
    使用flask提交表单的方式 1、前端html: {% extends "base.html" %} {% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky{% endblock %} {% block page_content %} Hello, {% if name %}{{ name ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 394,167
精华内容 157,666
关键字:

创建表单