随笔 - 241  文章 - 1  评论 - 58  阅读 - 85万 

一、Form组件:

django框架提供了一个form类,来处理web开发中的表单相关事项。众所周知,form最常做的是对用户输入的内容进行验证,为此django的forms类提供了全面的内容验证和保留用户上次输入数据的支持。

 form组件有2大大功能

对用户提交的内容进行验证(form表单/Ajax)

保留用户上次输入的内容

 

1、对用户提交的数据进行验证

form组件验证的原理

 

1.obj=Form()form组件类实例化时找到类中所有的字段 把这些字段 变成组合成字典;

self.fields={‘user’:正则表达式1,‘pwd’:正则表达式2}

2.循环self.fields字典(自己写的字段)

for  k,v  in self.fields.items():

    K是user,pwd

   v是正则表达式

3.每次循环通过self.fields字典的键, 一个一个的去get前端POST提交的数据 得到用户输入数据;

input_value= request.post.get(‘k’)(所以form字段的名称,要和前端的name属性匹配)

4.每次拿到用户输入的数据 (input_value)和进行正则表达式匹配;

5.匹配成功flag=True 匹配失败flag=falsh,最后 return flag  obj.is_valid=flag。

如果For自带的规则和正则满足不了验证需求,可在Form类中自定义方法,做扩展。

6.每个字段验证通过后,每个字段执执行self.clean_filelds函数(自定义 对Form类中的字段做单独验证,比如去数据库查询判断一下用户提交的数据是否存在?)

7. 执行Form组件的clean_form方法进行整体验证!(既然每个字段都验证了,就可以对用户提交的数据做整体验证了!比如进行联合唯一的验证)

 8.最后执行类似 clean_form的post_clean方法结束验证。(一般不使用post_clean做自定义过滤,clean_form方法完全可以解决)

form表单提交验证(form表单(会发起 get)提交刷新失去上次内容)

复制代码
from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields

class Login(Form):
                              #from验证规则 用户名 6-10字符  required不能为空
    name=fields.CharField(max_length=10,
                          min_length=6,
                          required=True,
                           error_messages={
                               'required':'用户名不能为空',  #error_messages参数 自定义错误信息
                               'min_length':'太短了',
                                'max_length': "太长了",
                                           }

                          )
                                                                    # z注意name 必须和 from表单提交的一致,要么二则怎么对比校验呢
    pwd= fields.CharField(min_length=3,
                          required=True,
                          error_messages={
                              'required': '密码不能为空',  # error_messages参数 自定义错误信息
                              'min_length': '太短了',
                              'max_length': "太长了",
                          }



                          )


def index(request):
    if request.method=='GET':
        return render(request,'login.html')
    else:
        obj=Login(request.POST)  #把客户端提交来的form表单和 和匹配规则放在一起
        res=obj.is_valid()         #自动校验  给出结果 True 或者 False
        if res:                    #验证成功后obj.cleaned_data获取成功的数据,字典类型正好对应数据 的批量操作
            print(obj.cleaned_data)
            return redirect('http://www.baidu.com')                 #obj.errors获取错误信息(对象类型)就可以传到前端显示了!
        else:
           return  render(request,'login.html',{'obj':obj})
View Code
复制代码

 

Aja提交验证(不会刷新,上次输入内容自动保留)

Django的form验证功能不仅限于对form表单提交的数据验证,同样适用于ajax提交方式;

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ajx提交</title>
</head>
<body>
<form method="post" action="/aja_login/" id="f1">
  {%csrf_token%}
<p>用户:<input type="text" name="name"></p>
<p>密码:<input type="password" name="pwd"></p>
<p><input type="button" onclick="Ajxform()" value="aja提交"></p>
</form>
</body>
<script src="/static/zhanggen.js"></script>
<script> function Ajxform(){
    $('.c1').remove()
    $.ajax({
        url:'/alogin/',
        type:'POST',
        dataType:'JSON',
        data:$('#f1').serialize(),
        success:function (args) {
            if (args.status){ }
            else{
{#                {status: false, msg: Object}#}
{#                console.log(args);#}
{#                Jquery循环服务端 传过来的 错误信息对象#}
                $.each(args.msg,function (index,value) {
                    console.log(index,value);
{#                 index----> name ["太短了"]#}
{#                 value-----pwd["密码不能为空"]#}
                    var tag=document.createElement('span');
                    tag.innerHTML= value[0];
                    tag.className='c1';
                    console.log(index);
{#                    寻找input下 属性为 name 和pwd的标签(字符串拼接) 在他们后半加 上tag标签也就是错误 信息 #}
                    $('#f1').find('input[name="'+ index +'"]').after(tag)

                })
            }

               }})}
</script>
</html>
View Code
复制代码

Views

复制代码
from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields
import json
class Login(Form):
                              #from验证规则 用户名 6-10字符  required不能为空
    name=fields.CharField(max_length=10,
                          min_length=6,
                          required=True,
                         error_messages={
                               'required':'用户名不能为空',  #error_messages参数 自定义错误信息
                               'min_length':'太短了',
                                'max_length': "太长了",
                                           }

                          )
                                                                    # z注意name 必须和 from表单提交的一致,要么二则怎么对比校验呢
    pwd= fields.CharField(min_length=3,
                          required=True,
                          error_messages={
                              'required': '密码不能为空',  # error_messages参数 自定义错误信息
                              'min_length': '太短了',
                              'max_length': "太长了",})



def agx_login(request):
    ret={'status':True,'msg':None}
    if request.method=='GET':
       return render(request,'ajalogin.html')
    else:
        obj=Login(request.POST)
        ret['status']=False
        ret['msg']=obj.errors
        return HttpResponse(json.dumps(ret))
View Code
复制代码

 

自定义正则表达式验证

密码修改实例

password_complexity='^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).+$' #密码复杂性要求:密码必须包含数字、大、写字母
复制代码
{% extends "arya/layout.html" %}
{% block  out_css %}
    <link rel="stylesheet" href="/arya/static/arya/css/form-control.css"/>
{% endblock %}

{% block content %}
    {% csrf_token %}
    <div>
        <div class="row">
            <a class="btn btn-default" href="{{ request.META.HTTP_REFERER }}">返回</a>
            <div class="col-md-5 col-md-offset-3">
                <form>
                    <div class="form-group">
                        <label for="exampleInputPassword1">请输入原始密码</label>
                        <input name="old_pwd" type="password" class="form-control" id="exampleInputPassword0"
                               placeholder="原始密码">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">新的密码</label>
                        <input name="first_new_pwd" type="password" class="form-control" id="exampleInputPassword1"
                               placeholder="新的密码">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">再次输入新密码</label>
                        <input name="second_new_pwd" type="password" class="form-control" id="exampleInputPassword2"
                               placeholder="再次输入新密码">
                    </div>

                    <button id="submit_pwd" type="button" class="btn btn-default">提交</button>

                </form>
                <br>
                <p style="color: red" id="__all__" class="error_msg"></p>
                <br>
                <p>设置密码时请符合以下规则:最小长度8、包含大小写英文字母、数字。</p>
            </div>
        </div>
    </div>
    {#    </section>#}
    <script>
        $('#submit_pwd').click(function () {
            var $csrf = $("[name='csrfmiddlewaretoken']").val();
            var $old_pwd = $('[name="old_pwd"]').val();
            var $first_new_pwd = $('[name="first_new_pwd"]').val();
            var $second_new_pwd = $('[name="second_new_pwd"]').val();

            var pwd_formdata = new FormData();
            pwd_formdata.append('csrfmiddlewaretoken', $csrf);
            pwd_formdata.append('old_pwd', $old_pwd);
            pwd_formdata.append('first_new_pwd', $first_new_pwd);
            pwd_formdata.append('second_new_pwd', $second_new_pwd);


            $.ajax({
                type: 'post',
                data: pwd_formdata,
                processData: false,
                contentType: false,
                success: function (data) {
                    var response = JSON.parse(data);
                    var $error_p = $('<p class="error_msg" style="color:red">'+ '</p>');

                    if (response.status == 200) {
                        window.location = "/login/"
                    }

                    if (response.status == 404) {
                        var error_p =$error_p.text(response.msg.old_pwd);
                        $('[name="old_pwd"]').after(error_p)
                    }
                    else {
                        $.each(response.msg, function (k, v) {
                            var $input_tag = $("[name=" + k +"]");
                            var error_p = '<p style="color: red" class="error_msg">'+v[0]+'</p>';
                            $input_tag.after(error_p);
                            console.log(response.msg);
                            if (k == '__all__') {
                                $('#__all__').text(v[0])
                            }
                        });
                    }

                    setTimeout("$('.error_msg').remove()", 3000);

                }
            })


        })
    </script>

{% endblock %}
前端模板
复制代码
复制代码
def changepwd(request):  #修改密码视图
    if request.method=='POST':
        current_user = request.session.get('username')
        response_info = {'status':200,'msg':None}
        user_db_obj = models.UserInfo.objects.filter(username=current_user).first()
        if not user_db_obj or user_db_obj.password != make_md5(request.POST.get('old_pwd').strip()):
            response_info['status'] = 404
            response_info['msg'] = {'old_pwd': '原始密码错误.'}
        else:
            obj = FormCheck.Set_password(request.POST)
            if not obj.is_valid():
                response_info['status'] = 403
                response_info['msg']=obj.errors
            else:
                user_db_obj.password = make_md5(request.POST.get('second_new_pwd').strip())
                user_db_obj.save()
        return HttpResponse(json.dumps(response_info, ensure_ascii=False))
    return render(request,'woke_order/changepwd.html')
Django视图
复制代码
复制代码
from django.forms import Form
from django.forms import fields
from django.forms import widgets
from cmdb.models import *
import re
from django.core.exceptions import ValidationError

class Set_password(Form):
    password_complexity='^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])).+$'

    old_pwd=fields.RegexField(password_complexity,
        required=True,
        min_length=8,
        error_messages={'invalid':'不满足密码复杂性要求','required':'密码不能为空!','min_length':'密码长度少于8位'},
    )

    first_new_pwd=fields.RegexField(password_complexity,
        required=True,
        min_length=8,
        error_messages={'invalid':'不满足密码复杂性要求','required':'密码不能为空!','min_length':'密码长度少于8位'},
    )

    second_new_pwd =fields.RegexField(password_complexity,
        required=True,
        min_length=8,
        error_messages={'invalid':'不满足密码复杂性要求','required':'密码不能为空!','min_length':'密码长度少于8位'},
    )

    def clean(self):
        first_new_pwd=self.cleaned_data.get('first_new_pwd')
        second_new_pwd=self.cleaned_data.get('second_new_pwd')
        if first_new_pwd and second_new_pwd:
            if first_new_pwd.strip() == second_new_pwd.strip():
                return self.cleaned_data
        raise ValidationError("两次密码不一致")
Django的form验证
复制代码

 

IP 和端口

ipaddr_validate="^((?:(2[0-4]\d)|(25[0-5])|([01]?\d\d?))\.){3}(?:(2[0-4]\d)|(255[0-5])|([01]?\d\d?))$"
port_validate='^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'
复制代码
from django.forms import Form,fields
from django.forms import widgets,forms
import re
ipaddr_validate="^((?:(2[0-4]\d)|(25[0-5])|([01]?\d\d?))\.){3}(?:(2[0-4]\d)|(255[0-5])|([01]?\d\d?))$"
port_validate='^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$'
class dbinfo_create(Form):
    data_mode_type=fields.CharField(required=True,error_messages={'required':'数据库模型不能为空.'})
    database_type=fields.CharField(required=True,error_messages={'required':'数据库类型不能为空'})
    host=fields.RegexField(ipaddr_validate,required=True,error_messages={'required':'IP不能为空','invalid':'不合法的IP地址'})
    port=fields.RegexField(port_validate,required=True,error_messages={'required':'端口不能为空.','invalid':'端口无效'})
    # instance_nikename=fields.CharField(max_length=20,error_messages={'required':'端口不能为空.',"max_length":"标题不能超过20个字"})
    db_business=fields.CharField(required=True,error_messages={'required':'请说明所属业务线'})
    DBA=fields.CharField(required=True,error_messages={'required':'请说明DBA'})
    responsible_person=fields.CharField(required=True, error_messages={'required':'请选择相关责任人!'})
验证
复制代码

 

 

 

 

 

2、动态生成HTML标签,保留用户上次输入的内容。

如何保留用户上次输入的内容?

由于form表单submit之后(发送post请求) 数据提交到 后端,不管前端输入的数据是否正确,服务端也要响应,所以页面会刷新;

所以无法保留用户上次输入的内容;如何解决呢?

 

1、把定义的定义的Form类,实例化(obj=Login() )内部调用一个__str__的方法,如果没有传值 返回<input type="text" name=“字段”>name='字段名空的input标签

2、把这个实例化之后的对象传到前端显示,让用户输入值;用户输入值通过post方法提交到后台。

3、如果后台实例化一个对象 obj=Login(request.POST)传入了值, <input type="text" name=“字段” value='request.post的数据'>然后后端再返回客户端就可以看到用户输入的值了!

 

 

 

保留用户上次输入的内容 是利用了 obj=Login(request.POST)接收了用户输入的值

视图

复制代码
from django import  forms

class Myform(forms.Form):            #1、写1个继承forms.Form的类,定制form表单的数据类型;
    user=forms.CharField(max_length=32,min_length=3,label='用户名',
                         error_messages={'required':'不能为空'},
                         widget=forms.TextInput(attrs={'class':'sb','placeholder':'用户名'},)
                         )
    age=forms.IntegerField(label='年龄',error_messages={'required':'不能为空'},)
    email=forms.EmailField(label='邮箱',error_messages={'required':'不能为空'},)

def register2(request):
    if request.method=='GET':
        forms_obj=Myform()               #2、实例化类,把对象渲染到模板
        return render(request,'form——register.html',{'forms_obj':forms_obj})
    else:
        forms_obj=Myform(request.POST)   #3、把提交的数据封装成form对象
        if forms_obj.is_valid():         #4、使用 form对象的.is_valid()方法,校验提交过来的数据是否符合验证规则
            data=forms_obj.cleaned_data  #5、获取验证通过的数据(字典类型,可直接 **dict插入数据库)
            # User.objects.create_user(**data)
            return HttpResponse('OK')
        else:
            print(forms_obj.cleaned_data) #6、由于用户在form表单提交了值,利用这一点,
                                            # 把forms_obj=Myform(request.POST)渲染到前端就可以保存用户输入的值
        return render(request, 'form——register.html', {'forms_obj':forms_obj})
View Code
复制代码

前台

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Django_form验证</title>
</head>
<body>
<form action="/form/" method="post" novalidate>
    {% csrf_token %}
    <p>用户:{{ forms_obj.user }}{{ forms_obj.errors.user.0 }}</p>
      <p>年龄:{{ forms_obj.age }}{{ forms_obj.errors.age.0}}</p>
    <p>邮箱:{{ forms_obj.email }}{{ forms_obj.errors.email.0}}</p>
    <button>提交</button>
</form>
</body>
</html>
View Code
复制代码

 

 

复制代码
from django.shortcuts import render,HttpResponse,redirect
from django.forms import Form
from django.forms import fields
import json
class Login(Form):
                              #from验证规则 用户名 6-10字符  required不能为空
    name=fields.CharField(max_length=10,
                          min_length=6,
                          required=True,
                         error_messages={
                               'required':'用户名不能为空',  #error_messages参数 自定义错误信息
                               'min_length':'太短了',
                                'max_length': "太长了",
                                           }

                          )
                                                                    # z注意name 必须和 from表单提交的一致,要么二则怎么对比校验呢
    pwd= fields.CharField(min_length=3,
                          required=True,
                          error_messages={
                              'required': '密码不能为空',  # error_messages参数 自定义错误信息
                              'min_length': '太短了',
                              'max_length': "太长了",})


def index(request):
    ret={'status':True,'msg':None}
    if request.method=='GET':
        obj=Login()                 #自动生成空白的input标签 发送给客户端)
        return render(request,'login.html',{'obj':obj})
    else:
        obj=Login(request.POST)  #把客户端提交来的form表单和 和匹配规则放在一
        res=obj.is_valid()         #自动生成空白的input标签 发送
        if res:                    #验证成功后obj.cleaned_data获取成功的数据,字典类型正好对应数据 的批量操作
            return HttpResponse('OK') #obj.errors获取错误信息(对象类型)就可以传到前端显示了!
        else:
           return render(request,'login.html',{'obj':obj})
View Code
复制代码
复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<form method="post" action="/login/" id="f1" novalidate >
     {%csrf_token%}
       <h1>用户登录</h1>
        <p>用户名 {{obj.name}}{{ obj.name.errors.0}}</p>
        <p>密码:{{ obj.pwd}}{{ obj.pwd.errors.0}}</p>
        <p><input type="submit" value="登录"></p>
</form>
</body>
</html>
View Code
复制代码

 

 

 

 3、承上启下 form组件的套路(执行流程):

(1)在后端定义类和字段,实例化Form类;

(2)到用户 发送get请求时,服务端渲染到模板(空标签/默认值)发送到客户端显示

(3)客户端填数据,POST提交到后端;

(4)后端验证,返回结果给前端;(切记Form组件是在后端生成,发送给客户端显示,客户端填完数据在发回服务端!)

 

二、form组件使用:

1、导入Form插件

from django.forms import Form,fields
from django.forms import widgets
复制代码
class Class_form(Form):
    title=fields.RegexField('全栈\d+',
                            # initial='全栈', #设置input标签中的默认值
                            min_length=2,
                            required=True,
                            error_messages={'invalid':"必须以全栈开头",
                                            'min_length':'太短了',
                                            'required':"不能为空",
                                            }
                            )
class Students(Form):
    name=fields.CharField(required=True,
    widget=widgets.TextInput(attrs={'class':'form-control'}),
    error_messages={'required':'姓名不能为空'})
    sex=fields.CharField(required=True,error_messages={'required':'不能为空'},
    widget = widgets.TextInput(attrs={'class': 'form-control'})

                         )
    cls_id=fields.IntegerField(widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),
    attrs = {'class': 'form-control'}

                                                     ),

                                )
class teacher_form(Form):
    tname=fields.CharField(required=True,error_messages={'required':"姓名不能为空"} )
   #  classes=fields.CharField( #多选 不能用这个插件不使用request.post.getlist()取值
   #      widget=widgets.Select(choices=models.Classes.objects.values_list(),
   #      attrs={'multiple':'multiple'})
   #                           )
   #  classes=fields.CharField(widget=widgets.SelectMultiple(
   # # 如果在fields.CharField字段该插件,得到会是{'tname': 'ww', 'classes': "['2', '3']"}字符串
   #   choices= models.Classes.objects.values_list('id','title')) )
    classes=fields.MultipleChoiceField(
        choices=models.Classes.objects.values_list('id','title'),
        widget=widgets.SelectMultiple,error_messages={'required':'选择不能为空'})
    def __int__(self,*args,**kwargs):  #解决数据不同步的bug,每次form组件实例化时 都重新去数据库拿数据
        super(teacher_form,self).__init__(*args,**kwargs)
        self.fields['classes'].widget.choices=models.Classes.objects.values_list('id','title')



class Test_form(Form):
    name=fields.CharField()  #动态生成 text类型的input标签
    text=fields.CharField(widget=widgets.Textarea,) #动态生成文本框
    age=fields.CharField(widget=widgets.CheckboxInput) #动态生成单选框
    holby=fields.MultipleChoiceField(                  #MultipleChoiceField动态生成复选框
        choices=[(1,'篮球'),(2,"足球"),(3,"高俅")],
        widget=widgets.CheckboxSelectMultiple)
    sex=fields.MultipleChoiceField(
        choices=[(1,''),(2,'')],
        widget=widgets.RadioSelect
    )

    select=fields.ChoiceField(choices=[(2, '北京'), (3, '唐县')]) #通过ChoiceField字段动态生成单选框
                                                                   # 通过form组件的MultipleChoiceField字段
    mselect=fields.MultipleChoiceField(choices=[(1,'管家佐'),(2,'万宝利') ],
                                 widget=widgets.SelectMultiple)
    file=fields.FileField()  #通过form组件的.FileField动态生成 文件上传input标签,注意在提交到后台是对象
View Code
复制代码


2、定义类和字段(验证规则) 扩展方法

class Form_login(Form):

                 字段                               参数

  user=fields.RegexField正则表达式,验证规则,error_messages={错误信息},widget=html标签插件attrs = {'标签插件的属性'})

 

四、form的钩子函数

Django的form在obj.is_valid()方法内提供2个钩子函数,以便我们随时调用他自定制一些复杂的验证规则;

 

 局部钩子函数 

复制代码
class Class_form(Form):
    title=fields.RegexField('全栈\d+',
                            # initial='全栈', #设置input标签中的默认值
                            min_length=2,
                            required=True,
                            error_messages={'invalid':"必须以全栈开头",
                                            'min_length':'太短了',
                                            'required':"不能为空",
                                            }
                            )
class Students(Form):
    name=fields.CharField(required=True,
    widget=widgets.TextInput(attrs={'class':'form-control'}),
    error_messages={'required':'姓名不能为空'})
    sex=fields.CharField(required=True,error_messages={'required':'不能为空'},
    widget = widgets.TextInput(attrs={'class': 'form-control'})

                         )
    cls_id=fields.IntegerField(widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),
    attrs = {'class': 'form-control'}

                                                     ),

                                )
class teacher_form(Form):
    tname=fields.CharField(required=True,error_messages={'required':"姓名不能为空"} )
   #  classes=fields.CharField( #多选 不能用这个插件不使用request.post.getlist()取值
   #      widget=widgets.Select(choices=models.Classes.objects.values_list(),
   #      attrs={'multiple':'multiple'})
   #                           )
   #  classes=fields.CharField(widget=widgets.SelectMultiple(
   # # 如果在fields.CharField字段该插件,得到会是{'tname': 'ww', 'classes': "['2', '3']"}字符串
   #   choices= models.Classes.objects.values_list('id','title')) )
    classes=fields.MultipleChoiceField(
        choices=models.Classes.objects.values_list('id','title'),
        widget=widgets.SelectMultiple,error_messages={'required':'选择不能为空'})
    def __int__(self,*args,**kwargs):  #解决数据不同步的bug,每次form组件实例化时 都重新去数据库拿数据
        super(teacher_form,self).__init__(*args,**kwargs)
        self.fields['classes'].widget.choices=models.Classes.objects.values_list('id','title')



class Test_form(Form):
    name=fields.CharField()  #动态生成 text类型的input标签
    text=fields.CharField(widget=widgets.Textarea,) #动态生成文本框
    age=fields.CharField(widget=widgets.CheckboxInput) #动态生成单选框
    holby=fields.MultipleChoiceField(                  #MultipleChoiceField动态生成复选框
        choices=[(1,'篮球'),(2,"足球"),(3,"高俅")],
        widget=widgets.CheckboxSelectMultiple)
    sex=fields.MultipleChoiceField(
        choices=[(1,''),(2,'')],
        widget=widgets.RadioSelect
    )

    select=fields.ChoiceField(choices=[(2, '北京'), (3, '唐县')]) #通过ChoiceField字段动态生成单选框
                                                                   # 通过form组件的MultipleChoiceField字段
    mselect=fields.MultipleChoiceField(choices=[(1,'管家佐'),(2,'万宝利') ],
                                 widget=widgets.SelectMultiple)
    file=fields.FileField()  #通过form组件的.FileField动态生成 文件上传input标签,注意在提交到后台是对象
View Code
复制代码

 全局钩子函数

如果要想要同时对2个form字段进行验证,就需要全局钩子函数(应用 验证2次输入的密码是否一致),可以调用他们自定制复杂的form验证规则,

问题1:  注册页面输入为空,报错:keyError:找不到password

复制代码
def clean(self):
        print("---",self.cleaned_data)
        #  if self.cleaned_data["password"]==self.cleaned_data["repeat_password"]:        
        #  报错原因:self.cleaned_data是干净数据,如果页面没有输入内容,则self.cleaned_data没有password。
        改如下:
        if self.cleaned_data.get("password")==self.cleaned_data.get("repeat_password"):
            return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致")
View Code
复制代码

 

 

  

四、渲染到模板

1.简单粗暴型

注意:模板语言{{form_obj.as_p}},一定要在设置lable参数

class UserInfoForm(Form):
    name=fields.CharField(required=True,error_messages={'reqired':'用户名不能为空'},label='姓名') 
    email=fields.EmailField(required=True,error_messages={'reqired':'用户名不能为空'},label='邮箱')
    pary=fields.ChoiceField(choices=[(1,"技术部"),(2,'销售部'),(3,'市场部'),],label='部门')

 

复制代码
{{obj.as_p}}以P标签的形式全部显示

<table> 注意加table标签形式全部显示
{{obj.as_table}}
</table>


<ul>注意加ul标签形式全部显示
{{obj.as_table}}
</ul>
View Code
复制代码

2.灵活定制型

复制代码
<p>姓名:{{ obj.name }}</p>
<p>性别:{{ obj.sex }}</p>
<p>爱好: {{ obj.holby }}</p>
<p>婚姻状况:{{ obj.age }}</p>
<p>个人简介 {{ obj.text }}</p>
<p>工作地点: {{ obj.select }}</p>
<p>居住地点:{{ obj.mselect }}</p>
<p>资料上传:{{obj.file}}</p>
View Code
复制代码

 

五、页面显示用户填完数据提交回来后台验证

数据校验

obj=classForm_login(request.POST )

默认校验:obj=classForm_login(data={} ) 含有错误信息: obj=Class_form(initial={'title':class_obj.title})只有html标签

obj.is_valid()  获取校验结果

obj.errors获取错误信息

obj.cleand_data 获取正确的数据

 

六、基于Form组件的学生管理系统(项目)

路由

复制代码
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^classes/',views.classes),
    url(r'^classes_add(\d+)/',views.classes_add),
    url(r'^classes_edit(\d+)/',views.classes_edit),
    url(r'^students/',views.students),
    url(r'^students_add(\d+)/',views.students_add),
    url(r'^students.edit(\d+)/',views.students_edit),
    url(r'^teachers/',views.teacher),
    url(r'^teacher_add/',views.teacher_add),
    url(r'^teacher_edit(\d+)/',views.teacher_edit),
    url(r'^test/',views.test),
]
View Code
复制代码

视图

复制代码
def classes(request):
    if request.method=='GET':
        c_list=models.Classes.objects.all()
        return render(request,'class_list.html',{'clist':c_list})

def classes_add(request,args):
    if request.method=='GET':
        obj=Class_form()
        return render(request,'class_add.html',{'obj':obj})
    else:
        obj=Class_form(request.POST)
        if obj.is_valid():
            models.Classes.objects.create(**obj.cleaned_data )
            return redirect('/classes/')
        else:
            print('NI')
            return render(request,'class_add.html',{'obj':obj})

def classes_edit(request,args):
    if request.method=='GET':
        class_obj=models.Classes.objects.filter(id=args).first()
        obj=Class_form(initial={'title':class_obj.title})
        return render(request,'class_edit.html',{'obj':obj,'nid':args})
    else:
        obj = Class_form(request.POST)
        if obj.is_valid():
            models.Classes.objects.filter(id=args).update(**obj.cleaned_data)
            return redirect('/classes/')
        else:
            return render(request, 'class_edit.html', {'obj': obj, 'nid': args})


def students(request):
    if request.method=='GET':
        students=models.Student.objects.all()
        return render(request,'students.html',{'student':students})

def students_add(request,nid):
    if request.method=='GET':
        obj=Students()
        return render(request,'student_add.html',{'obj':obj,'nid':nid})
    else:
        obj=Students(request.POST)
        if obj.is_valid():
            models.Student.objects.create(**obj.cleaned_data)
            return redirect('/students/')
        else:
            return render(request,'student_add.html',{'obj':obj,'nid':nid})


def students_edit(request,nid):
    if request.method=='GET':
        # print(models.Student.objects.filter(id=nid).values('name','sex','cls_id').first())
        obj=Students(initial=models.Student.objects.filter(id=nid).values('name','sex','cls_id').first())
        return render(request,'student_edit.html',{'obj':obj,'nid':nid})
    else:
        obj1=Students(request.POST)
        if obj1.is_valid():
            models.Student.objects.filter(id=nid).update(**obj1.cleaned_data)
            return redirect('/students/')
        else:
            return render(request, 'student_edit.html', {'obj': obj1, 'nid': nid})

def teacher(request):
    if request.method=='GET':
        teacher_list=models.teacher.objects.all()
        return render(request,'teacher_list.html',{'tlist':teacher_list})

def teacher_add(request):
    if request.method=='GET':
        print(request.method)
        obj=teacher_form()
        return render(request,'teacher_add.html',{'obj':obj})
    else:
        obj=teacher_form(request.POST)
        if obj.is_valid():
            classe_ids=obj.cleaned_data.pop('classes') #老师任教的班级
            tname=obj.cleaned_data   #老师的姓名
            create_teacher=models.teacher.objects.create(**tname)
            create_teacher.c2t.add(*classe_ids)
            return redirect('/teachers/')
        else:
            return render(request,'teacher_add.html',{'obj':obj})









def teacher_edit(request,arg):
    if request.method=='GET':
        teacher_obj=models.teacher.objects.filter(id=arg).first()
        classes_ids=teacher_obj.c2t.values_list('id')
        cid_list=list(zip(*classes_ids))[0] if list(zip(*classes_ids)) else[]
        # print(cid_list) 元组
        obj=teacher_form(initial={'tname':teacher_obj.tname,'classes':cid_list})
        return render(request,'teacher_edit.html',{'obj':obj,'nid':arg} )
    else:
        obj=teacher_form(request.POST)
        if obj.is_valid():
            teacher_name=obj.cleaned_data.pop('tname')
            models.teacher.objects.filter(id=arg).update(tname=teacher_name)
            obj1=models.teacher.objects.filter(id=arg).first()
            classes=obj.cleaned_data.pop('classes')
            obj1.c2t.set(classes)
            return redirect('/teachers/')
        else:
            return render(request,'teacher_add.html',{'obj':obj})








def test(request):
    if request.method=='GET':
        obj=Test_form(initial={'holby':[ 1,2],'name':'张根','text':'我来自太行山','sex':1})
        # # print(models.Student.cls.objects.values_list())
        # obj=models.Student.objects.filter(id=1).first()
        # print(obj.cls.title)
        return render(request,'test.html',{'obj':obj})
View Code
复制代码

form组件

复制代码
from django.shortcuts import render,HttpResponse,redirect
from  app01 import models
from django.forms import Form,fields
from django.forms import widgets

class Class_form(Form):
    title=fields.RegexField('全栈\d+',
                            # initial='全栈', #设置input标签中的默认值
                            min_length=2,
                            required=True,
                            error_messages={'invalid':"必须以全栈开头",
                                            'min_length':'太短了',
                                            'required':"不能为空",
                                            }
                            )
class Students(Form):
    name=fields.CharField(required=True,
    widget=widgets.TextInput(attrs={'class':'form-control'}),
    error_messages={'required':'姓名不能为空'})
    sex=fields.CharField(required=True,error_messages={'required':'不能为空'},
    widget = widgets.TextInput(attrs={'class': 'form-control'})

                         )
    cls_id=fields.IntegerField(widget=widgets.Select(choices=models.Classes.objects.values_list('id','title'),
    attrs = {'class': 'form-control'}

                                                     ),

                                )
class teacher_form(Form):
    tname=fields.CharField(required=True,error_messages={'required':"姓名不能为空"} )
   #  classes=fields.CharField( #多选 不能用这个插件不使用request.post.getlist()取值
   #      widget=widgets.Select(choices=models.Classes.objects.values_list(),
   #      attrs={'multiple':'multiple'})
   #                           )
   #  classes=fields.CharField(widget=widgets.SelectMultiple(
   # # 如果在fields.CharField字段该插件,得到会是{'tname': 'ww', 'classes': "['2', '3']"}字符串
   #   choices= models.Classes.objects.values_list('id','title')) )
    classes=fields.MultipleChoiceField(
        choices=models.Classes.objects.values_list('id','title'),
        widget=widgets.SelectMultiple,error_messages={'required':'选择不能为空'})
    def __int__(self,*args,**kwargs):  #解决数据不同步的bug,每次form组件实例化时 都重新去数据库拿数据
        super(teacher_form,self).__init__(*args,**kwargs)
        self.fields['classes'].choices=models.Classes.objects.values_list('id','title')



class Test_form(Form):
    name=fields.CharField()  #动态生成 text类型的input标签
    text=fields.CharField(widget=widgets.Textarea,) #动态生成文本框
    age=fields.CharField(widget=widgets.CheckboxInput) #动态生成单选框
    holby=fields.MultipleChoiceField(                  #MultipleChoiceField动态生成复选框
        choices=[(1,'篮球'),(2,"足球"),(3,"高俅")],
        widget=widgets.CheckboxSelectMultiple)
    sex=fields.MultipleChoiceField(
        choices=[(1,'男'),(2,'女')],
        widget=widgets.RadioSelect
    )

    select=fields.ChoiceField(choices=[(2, '北京'), (3, '唐县')]) #通过ChoiceField字段动态生成单选框
                                                                   # 通过form组件的MultipleChoiceField字段
    mselect=fields.MultipleChoiceField(choices=[(1,'管家佐'),(2,'万宝利') ],
                                 widget=widgets.SelectMultiple)
    file=fields.FileField()  #通过form组件的.FileField动态生成 文件上传input标签,注意在提交到后台是对象
View Code
复制代码

 

模板

班级管理(1对1)

班级显示

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>班级列表</title>
    <link rel="stylesheet" href="/static/bootstrap-3.3.5-dist/css/bootstrap.css">
</head>
<body>
<div style="width: 500px;margin: 0 auto">
<h1>班级列表</h1>
<ul>
    {% for obj in clist %}
        <li>{{ obj.title }}
            <a href="/classes_add{{ obj.id }}/">添加</a>
            <a href="/classes_edit{{ obj.id }}/">编辑</a>
        </li>
    {% endfor %}
</ul>
</div>
</body>
</html>
View Code
复制代码

添加班级

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加班级</title>
</head>
<body>
<h1>添加班级</h1>
<form action='/classes_add{{2}}/' method="post" novalidate>
    {% csrf_token %}
  <p>班级添加:{{ obj.title}} {{ obj.errors.title.0}}</p>
   <p><input type="submit" value="提交"></p>
</form>

</body>
</html>
View Code
复制代码

编辑班级

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>编辑班级</title>
</head>
<body>
<form action="/classes_edit{{nid}}/" method="post">
    {% csrf_token %}
   <p>编辑班级:{{ obj.title }}{{obj.title.errors.0}} </p>
    <input type="submit" value="提交">
</form>
</body>
</html>
View Code
复制代码

 

学生管理1对多

学生显示

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学生管理</title>
</head>
<body>
<h1>学生管理</h1>
<ul>
    {% for row in student %}
        <li>{{row.name}}
            {{row.sex}}
            <a href="/students_add{{row.id}}/">添加</a>
            <a href="/students.edit{{row.id}}/">编辑</a>
        </li>
    {% endfor %}
</ul>
</body>
</html>
View Code
复制代码

学生添加

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <h1>添加学生</h1>
    <meta charset="UTF-8">
    <title>添加学生</title>
</head>
<body>
<form action="/students_add{{ nid}}/" method="post" novalidate>
     {% csrf_token%}
<p>姓名:{{ obj.name}}{{obj.name.errors.0}}</p>
<p>性别:{{ obj.sex}}{{obj.sex.errors.0}} </p>
<p>班级:{{ obj.cls_id }}{{ obj.errors.0}}  </p>
<p><input type="submit" value="提交"></p>
 </form>
</body>
</html>
View Code
复制代码

学生编辑

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>老师编辑</title>
</head>
<body>
<form action="/teacher_edit{{ nid }}/" method="post">
    {% csrf_token %}
<p>老师姓名:{{obj.tname }}</p>
<p>班级:{{ obj.classes }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>
View Code
复制代码

 

 老师管理多对多

老师显示

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>老师列表</title>
</head>
<body>
<table border="1">
<thead>
<tr><td>ID</td><td>老师</td><td>任教班级</td><td colspan="3">操作</td></tr>
</thead>
<tbody>
     {% for teacher in tlist %}
    <tr>
        <td>{{ teacher.id }}</td>
        <td>{{teacher.tname}}</td>
        <td>
            {% for row in teacher.c2t.values %}
            {{ row.title }}
            {% endfor %}
         </td>
        <td><a href="/teacher_add/">添加</a></td>
        <td><a href="/teacher_edit{{ teacher.id}}/">编辑</a></td>
    </tr>
    {% endfor %}
</tbody>
</table>



</body>
</html>
View Code
复制代码

老师添加

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加老师</title>
</head>
<body>
<form action="/teacher_add/" method="post" novalidate>
{% csrf_token %}
<p>老师姓名:{{ obj.tname }}{{obj.tname.errors.0}}</p>
<p>任教班级:{{ obj.classes }}{{obj.classes.errors.0}}</p>
<p><input type="submit" value="提交"></p>
 </form>
</body>
</html>
View Code
复制代码

老师编辑

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>老师编辑</title>
</head>
<body>
<form action="/teacher_edit{{ nid }}/" method="post">
    {% csrf_token %}
<p>老师姓名:{{obj.tname }}</p>
<p>班级:{{ obj.classes }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>
View Code
复制代码

 

 PS:Form验证组件验证ajax提交的json

Django的form组件,不仅可以对 浏览器端 提交过来的form表单数据做验证,还可以对ajax提交的 json数据 做验证,但是需要在发送之前获取CSRF-tocken设置在请求头中;

复制代码
 $.ajax({
                type: 'POST',
                async: false,
                cache: false,
                url: '{% url "instance_add" %}',
                 headers:{"X-CSRFToken":$.cookie('csrftoken')},
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                traditional:true,
                data:JSON.stringify({
                    "data_mode_type": $data_mode_type,
                    'database_type': $database_type,
                    'host': $host,
                    'port': $port,
                    'instance_nikename': $instance_nikename,
                    'db_business': $db_business,
                    'DBA': $DBA,
                    'responsible_person': $responsible_person
                }),
                success: function (data) {
                   alert(1)
                }
            });
        })
前端
复制代码
复制代码
from django.shortcuts import render,HttpResponse,redirect
from DB_auto.form_validate.add_dbinfo import dbinfo_create
import json

def instance_add(request):
    if request.method=='POST':
        json_data=json.loads(request.body.decode('utf-8'))
        obj=dbinfo_create(json_data)
        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            print(obj.errors)
    return render(request,'add_dbinfo.html')
django后台
复制代码

 

 

 

 七、ModelForm

使用Django开发web程序阶段回顾:

1.手动对单表进行增、删、该、查,手动把ORM操作获取的数据渲染到模板;(阶段1)

2.Form组件(类),自动生成标签(input、select),并对用户输入的数据做规则验证;(阶段2)

 

3.ModelForm顾名思义就Form和Django的Model数据库模型结合体,可以简单、方便得对数据库进行增加、编辑操作和验证标签的生成

 

Form组件和ModelForm的区别

ModelForm是Django Model.py和Form组件的结合体,可以简单/快速使用 Form验证和数据库操作功能,但不如Form组件灵活,如果在使用Django做web开发过程中验证的数据和数据库字段相关(可以对表进行增、删、改操,注意 Many to many字段,也可以级联操作第3张关系表;),建议优先使用ModelForm,用起来更方便些,但是在使用ModelForm的时候慎用fields='__all__',获取数据库所有字段势必造成性能损耗;

 

使用ModelForm

前端:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{{ form_obj.as_p }}
{#<p>姓名:{{form_obj.name  }}</p>#}
</body>
</html>
View Code
复制代码

 

后端视图:

复制代码
from app02 import models
from django.forms import ModelForm
class UserModalForm(ModelForm):
    class Meta:
        model=models.UserInfo #(该字段必须为 model  数据库中表)
        fields= '__all__'   #(该字段必须为 fields 数据库中表)

def add(request):
     # 实例化models_form
    if request.method=='GET':
        obj = UserModalForm()
        return render(request,'rbac/user_add.html',locals())
    else:
        obj=UserModalForm(request.POST)
        if obj.is_valid():
            data=obj.cleaned_data
            obj.save()  #form验证通过直接 添加用户信息到数据库
        return render(request, 'rbac/user_add.html', locals())
View Code
复制代码

 

 model.py

 

使用使用Form组件和ModelForm注意事项:

1、model.py一点要写verbose_name='名称'参数,才会在前端显示P标签的标题;

复制代码
from django.db import models

class Department(models.Model):
    title=models.CharField(max_length=32,verbose_name='部门名称')
    def __str__(self):
        return self.title

class UserInfo(models.Model):
    name=models.CharField(max_length=32,verbose_name='姓名')
    emai=models.EmailField(max_length=32,verbose_name='邮箱')
    pary=models.ForeignKey(Department,verbose_name='部门')
View Code
复制代码

 

如果使用Form组件在前端显示标题,可以设置Form类中的lable参数

复制代码
class UserInfoForm(Form):
    name=fields.CharField(required=True,error_messages={'reqired':'用户名不能为空'},label='姓名')
    email=fields.EmailField(required=True,error_messages={'reqired':'用户名不能为空'},label='邮箱')
    pary=fields.ChoiceField(choices=[(1,"技术部"),(2,'销售部'),(3,'市场部'),],label='部门')
View Code
复制代码

 

 

2、pary=fields.ChoiceField(choices=models.Department.objects.values_list('pk','title'),label='部门'),前端select标签不能随数据库操作实时更新;

在Department表添加一条数据之后,前端select标签中的数据不能随数据库实时更新;

 

原因:

不管是ModelForm还是Form组件本质就是个类,fields(字段)本质就是类中的1个静态属性,在类第一次加载时赋值,永远不会更新;

 

 

 

解决方案1(手动档):

重写__init__方法,每次实例化对象,就去获取一次数据库内容,重新赋值;

复制代码
class UserInfoForm(Form):
    name=fields.CharField(required=True,error_messages={'reqired':'用户名不能为空'},label='姓名')
    email=fields.EmailField(required=True,error_messages={'reqired':'用户名不能为空'},label='邮箱')
    pary=fields.ChoiceField(label='部门')
    # pary=fields.ChoiceField(choices=models.Department.objects.values_list('pk','title'),label='部门')
    def __init__(self,*args,**kwargs):
        super(UserInfoForm,self).__init__(*args,**kwargs)
        self.fields['pary'].choices=models.Department.objects.values_list('pk','title')
View Code
复制代码

 

解决方案2(自动档)

导入ModelChoiceField 模块  from django.forms.models import ModelChoiceField 

使用ModelChoiceField 字段

复制代码
from django.forms import fields
from django.forms import widgets
from django.forms import ModelForm
from django.forms.models import ModelChoiceField

class UserInfoForm(Form):
    name=fields.CharField(required=True,error_messages={'reqired':'用户名不能为空'},label='姓名')
    email=fields.EmailField(required=True,error_messages={'reqired':'用户名不能为空'},label='邮箱')
    #方案1
    pary=ModelChoiceField(queryset=models.Department.objects.all(),label='部门')
View Code
复制代码

 

自动挡虽好,但是也有缺陷;前端option标签的内容,需要借助model.py中的__str__方法,生成;

 

 

 

 

八、扩展 widgets之富文本编辑框

 如果你的web应用涉及到了发表文章、表情评论就必须使用富文本编辑框,小编调研了两款 Kindeditor、CKeditor;

 

Kindeditor

1.Kindeditor简介

http://kindeditor.net/docs/usage.html

2.下载Kindeditor编辑器

http://www.kindsoft.net/down.php

3.引入Kindeditor编辑器

<script src="/static/kindeditor-4.1.10/kindeditor-all.js"></script>

 

4.使用Kindeditor编辑器

 

a.创建textarea 标签

<textarea name="content" id="a" cols="30" rows="10"></textarea>

b.初始化Kindeditor

<script>
  var edit=KindEditor.create('#a',{
        width:'700px',
        height:'500px',
        uploadJson:'/upload_file/',
        extraFileUploadParams:{
            'csrfmiddlewaretoken':'{{ csrf_token }}',}})
</script>

 

c. Kindeditor功能定制

复制代码
<script>
        var edit = KindEditor.create('#a', {
            items: [ //填写自己想要的功能
                'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
                'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
                'insertunorderedlist', '|', 'emoticons', 'image', 'link'],
            width: '700px',
            height: '500px',
            uploadJson: '/upload_file/',
            extraFileUploadParams: {
                'csrfmiddlewaretoken': '{{ csrf_token }}',
            }
        })
    </script>
复制代码

 

d.kindeditor的API

复制代码
// 取得HTML内容
html = editor.html();

// 同步数据后可以直接取得textarea的value
editor.sync();
html = document.getElementById('editor_id').value; // 原生API
html = K('#editor_id').val(); // KindEditor Node API
html = $('#editor_id').val(); // jQuery

// 设置HTML内容
editor.html('HTML内容');
复制代码

 

CKeditor结合Django Form

1.下载  django-ckeditor 和pillow

pip install django-ckeditor 
pip install pillow

2.setings

复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rbac.apps.RbacConfig',
    'arya.apps.AryaConfig',
    'cmdb.apps.CmdbConfig',
    'rest_framework',
    'ckeditor',
    # 'ckeditor_uploader'
]
复制代码

 

复制代码
CKEDITOR_CONFIGS = {
    'default': {
        'toolbar': (
            # ['div','Source','-','Save','NewPage','Preview','-','Templates'],
            # ['Cut','Copy','Paste','PasteText','PasteFromWord','-','Print','SpellChecker','Scayt'],
            # ['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
            # ['Form','Checkbox','Radio','TextField','Textarea','Select','Button', 'ImageButton','HiddenField'],
            # ['Bold','Italic','Underline','Strike','-','Subscript','Superscript'],
            # ['NumberedList','BulletedList','-','Outdent','Indent','Blockquote'],
            # ['JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock'],
            # ['Link','Unlink','Anchor'],
            ['Smiley',],

            # ['Styles','Format','Font','FontSize'],
            # ['TextColor','BGColor'],
            # ['Maximize','ShowBlocks','-','About', 'pbckcode'],

        ),
    }
}
功能定制
复制代码

 

3. 收集Django 项目所有 静态文件  到的目录static目录   /   直接下载ckeditor到项目static

复制代码
python  manage.py collectstatic

#设置媒体文件的上传的路径
MEDIA_URL="/media/"
#MEDIA_ROOT=os.path.join(BASE_DIR,"media")
MEDIA_ROOT='/tmp/cmdb_media/'



STATIC_ROOT = os.path.join(BASE_DIR, 'static')
设置media路径+static路径
复制代码

 

注意:此步骤如果提示 需要你设置MEDIA_URL目录 和STATIC_ROOT 就先暂且设置一下,最终目的是把CKeditor的js插件copy到你的静态文件存放目录下;

 

4.后端生成 textarea +加前端 ckedit 插件生成 富文本编辑

from ckeditor.widgets import CKEditorWidget
class comment(Form): #评论框
    content =fields.CharField(widget=CKEditorWidget)
复制代码
 {{ obj.content|safe }}

<script src="/static/pligin/ckeditor/ckeditor-init.js"></script>
<script src="/static/pligin/ckeditor/ckeditor/ckeditor.js"></script>
View Code
复制代码

 

5.CKEditorWidget API

复制代码
  <script>
        $('.root_reply_btn').click(function () {
            var $reply_user = $(this).attr('name');
            var $pid = $(this).attr('pid');
            $('#comment_submit').attr('pid', $pid);
            CKEDITOR.instances.id_content.insertText('回复' + $reply_user + ':');
            CKEDITOR.instances.id_content.insertHtml('<br>');
            CKEDITOR.instances.id_content.focus(); #使CKEditorWidget进入编辑状态 (MD在后台测试了半天!!)


        });
CKEDITOR.instances.id_content.document.$.body.firstChild.textContent 获取p标签的文本内容
</script>
复制代码

 

6.完成效果

 

 

 

 

 

 

 

 

 

 

 

 

博客链接:http://www.cnblogs.com/wupeiqi/articles/6144178.html

http://www.cnblogs.com/yuanchenqi/articles/7439088.html#3770465

DjangoForm补充:http://www.cnblogs.com/yuanchenqi/articles/7487059.html

posted on   Martin8866  阅读(7353)  评论(2编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示