首发于 肥乡杂谈

【实战演练】Python+Django网站开发系列08-JavaScript/JQuery前后端交互

#本文欢迎转载,转载请注明出处和作者

1、修改密码

编辑mopasswd.html页面,使用magicbox快速拖拉拽出一个前端页面(主要是form表单),然后将代码粘贴进html页面进行修改。

如果忘记了magixbox前端页面的使用,可以参考之前文章:

<form class="form-horizontal" method="post">
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">原密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="oldpassword" placeholder="请输入原密码">
            </div>
        </div>
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">新密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="newpassword1" placeholder="请输入新密码">
            </div>
        </div>
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">确认新密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="newpassword2" placeholder="请再次输入新密码">
            </div>
        </div>
        <div class="form-group clearfix">
            <div class="col-sm-9 col-sm-offset-3">
                <button type="submit" class="king-btn mr10  king-success">提交</button>
                <button type="button" class="king-btn king-default ">取消</button>
            </div>
        </div>
    </form>

编辑views.py的函数,增加业务逻辑。

def mopasswd(request):
    if request.method == 'POST' and request.POST:
        oldpassword = request.POST['oldpassword']
        newpassword1 = request.POST['newpassword1']
        newpassword2 = request.POST['newpassword2']
        username = request.session['username']
        userinfo = auth.authenticate(username=username, password=oldpassword)
        if userinfo and newpassword1 == newpassword2:
            user = User.objects.get(username=username)
            user.set_password(newpassword2)
            user.save()
            return render(request, 'mopasswd.html')
    return render(request,'mopasswd.html')

其中,用了auth.authenticate判断了当前用户名密码认证是否通过,以及newpassword1 == newpassword2判断了2次新密码是否相同,当上述两个条件都满足,就会修改密码。

修改完成后,注销然后重新登录,使用新密码登录,测试新密码是否能够成功修改。

但是其实当前的用户体验是非常不友好的,因为无论密码修改成功与否(可能有多种因素导致不成功),都没有任何提示,都是会刷新回返到修改用户密码界面。因此如果需要有反馈提示给用户修改失败,可以考虑两种方式:

1)直接在提交按钮或者用户名密码输入框下面,文字显示错误提示。例如两次输入的新密码不一致,或者密码不能为空。需要提前在提示未知预留一个标签,然后使用JavaScript来进行判断,然后根据不同的判断结果,进行不同的动作。

2)弹层:即在页面上面再弹一层对话框出来,提示错误情况。

下面针对两种方式的实现分开讲述。

2、JavaScript简介

JavaScript是一种脚本语言,与C语言、Python等一样有各种变量、if...else、for等语句,这里我们只针最常用的部分做一些介绍,更多详细的JavaScript教程,可参考W3School的教程:

2.1变量

JavaScrpit的变量,需要用var声明,并且语句要用分号结束

var username;

与CSS类似,可以用#或者.来获取HTML对象,其中:

$("#XXX")是匹配id="XXX"的元素

$(".XXX")是匹配class="XXX"的元素

$("#XXX").val()是id="XXX"的元素的值,这样就可以获取特定id的<input>标签的值了。

2.2函数

正常书写JavaScript函数,与其他语言一样,function(){},在花括弧里面编写内容。

function functionname(){
    $("#button").click()

但是JavaScript函数内嵌在HTML页面里面的时候,写法不一样,要在外面包一层$()

$(
    function functionname(){
        $("#button").click()

2.3引用

2.3.1内嵌到HTML页面

JavaScript引用方式常用的有2种,一种是直接内嵌在HTML页面里面,在页面最下方编写,但是这种方式的JavaScript会在加载HTML页面的时候,自动执行一次。

在BASE02.html的</html>标签下面,添加如下代码。

<script>
        function clicktest(){
            $("#newpasswordinfo").text("这就是按下的效果")
</script>

然后修改mopasswd.py文件的“提交”按钮的type为button,然后增加onclick="clicktest()",表示当按下“提交”按钮,会执行该函数的动作。

<button type="button" class="king-btn mr10  king-success" onclick="clicktest()">提交</button>

刷新页面查看,但是发现直接就显示了“这就是按下的效果”,因为这种方式会在加载HTML页面的时候也执行JavaScript脚本。

2.3.2引用独立JS文件

另外一种方式是将函数写到JS文件里面,然后在HTML里面引用该文件。JS文件一般都会在/static/目录下建立一个JS文件夹,然后把JS脚本放在里面。而单独的JS文件写函数,就不需要用$()来引用了。

在/static/js/下新建一个stumgrtjs.js文件,编写如下代码:

function clicktest(){
    $("#newpasswordinfo").text("这就是按下的效果")

在BASE02.html下面引用JS

<script type="text/javascript" src="/static/js/stumgrjs.js"></script>

重新刷新mopasswd页面,发现文字提示没有了。

修改mopasswd.py文件的“提交”按钮的type为button,然后增加onclick="clicktest()",表示当按下“提交”按钮,会执行该函数的动作。

<button type="button" class="king-btn mr10  king-success" onclick="clicktest()">提交</button>

点击“提交”按钮之后,文字出现。

这就是HTML独立引用JS文件,然后通过绑定按钮来调用JS函数。

3、JQuery

3.1引用jquery

JQuery是高度封装的JavaScript,用来与后台交互数据比较方便,使用需要像CSS一样进行引用。(也可以下载到本地,然后放入/static/js/文件夹进行本地引用。)下载地址:

我们在BASE页面里面加入JQuery引用,可以使用在线引用。

<script src="https://magicbox.bk.tencent.com/static_api/v3/assets/js/jquery-1.10.2.min.js"></script>

也可以使用本地引用,前提是先将文件下载到本地。

<script src="/static/js/jquery-1.10.2.min.js"></script>

3.2jquery的post请求

jquery的post请求格式如下:

$.post(url,{json格式的数据},function (条件) {
           具体业务函数
    },'返回的数据格式')

一般示例如下:

$.post('/changepassword/',{
    'username':$('#username').val(),
    'password':$('#password').val(),
    },function (res) {
            alert("添加成功!");
            window.location.reload();
    },'json')

/changepassword/为具体url,会到urls.py匹配具体的函数。

'username'等用了json格式组织数据,$('#username').val()为id='username'的输入框的具体数值。

post会将'username','password',通过post方法,将数据推送给/changepassword/对应的函数。

function里面的res,是接收/changepassword/对应的函数返回的数据,如果有数据返回,则会执行function里面的业务逻辑,如果没有任何数据返回,则不会执行function里面的业务逻辑。

最后面的'json'是指post使用怎样的格式将数据推送给/changepassword/对应的函数。

3.3jquery的ajax请求

ajax是jquery另外一种向后台推送数据的方法,格式如下:

$.ajax(
    url:url,
    type:"post",
    data:{
    beforeSend:function(){},
    async:true,
    success:function(){
    error:function(){

一般示例如下:

$.ajax(
    url:'/changepassword/',
    type:"post",
    data:{
        'username':$('#username').val(),
        'password':$('#password').val(),
    beforeSend:function(){},
    async:true,
    success:function(res){
        alert("添加成功!");
        window.location.reload();
    error:function(){

使用方法基本上与上面的post是一样的,不在赘述。

4、修改密码业务逻辑编写

首先由于前端现在改由JQuery来提交数据给后台,所以不用html的原生form来提交数据了,form里面有些东西需要修改。

<form class="form-horizontal" method="post">
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">原密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="oldpassword" id="oldpassword"
                       placeholder="请输入原密码">
            </div>
        </div>
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">新密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="newpassword1" id="newpassword1"
                       placeholder="请输入新密码">
            </div>
        </div>
        <div class="form-group clearfix ">
            <label class="col-sm-3 control-label bk-lh30 pt0">确认新密码:</label>
            <div class="col-sm-9">
                <input type="password" class="form-control bk-valign-top" name="newpassword2" id="newpassword2"
                       placeholder="请再次输入新密码">
                <p class="help-block" id="newpasswordinfo"></p>
            </div>
        </div>
        <div class="form-group clearfix">
            <div class="col-sm-9 col-sm-offset-3">
                <button type="button" class="king-btn mr10  king-success" onclick="changepassword()">提交</button>
                <button type="button" class="king-btn king-default ">取消</button>
            </div>
        </div>
    </form>

首先,由于JavaSript使用id与class来匹配元素而不是用name,所以每个<input>标签,需要增加id=""的属性。

其次,“提交”按钮的type要从submit修改回button,变回普通的按钮,然后onclick修改为调用一会儿stumgrtjs.js里面新增的changepassword()函数。

然后,编写stumgrtjs.js文件,里面增加changepassword()函数。

function changepassword() {
    if ($('#oldpassword').val() == '' || $('#newpassword1').val() == '' || $('#newpassword2').val() == '') {
        $("#newpasswordinfo").text("密码不能为空!");
    } else if ($('#newpassword1').val() != $('#newpassword2').val()) {
        $("#newpasswordinfo").text("两次输入的新密码不一致!");
    } else {
        $.post('/changepassword/', {
            'oldpassword': $('#oldpassword').val(),
            'newpassword1': $('#newpassword1').val(),
            'newpassword2': $('#newpassword2').val(),
        }, function (res) {
            if(res.result){
                alert("修改成功!");
                window.location.reload();
            }else{
                alert("旧密码不正确,请重新输入!");
                window.location.reload();
        }, 'json')

核心业务逻辑为$.post(){}里面的内容,将oldpassword,newpassword1,2都推送给/changepassword/这个url对应的函数。(当然urls.py里面也要增加对应的路由,另外views.py里面也要增加对应的函数。)

urlpatterns = [
    ......
    url(r'^changepassword/', changepassword),
]

function(res)检测是否有数值返回,if...else是根据返回的结果,判断修改是否成功,然后弹层提示告知用户。

前面一段if、else if、else分别是用来检测输入的<input>是否空值,2次新密码是否一致,不一致直接文件返回提示到预留的<p>标签。

前面我们都是把修改密码的业务逻辑直接写在views.py里面的mopasswd函数里面的,但是其实motchpasswd(修改老师用户密码)的业务逻辑是一样的,而且现在修改为用JQuery来提交数据了,因此可以直接把业务逻辑分离出来,单独用一个函数表示。那么上述mopasswd与motchpasswd两个页面都能复用这段代码。

def changepassword(request):
    if request.method == 'POST' and request.POST:
        oldpassword = request.POST['oldpassword']
        newpassword2 = request.POST['newpassword2']
        username = request.session['username']
        userinfo = auth.authenticate(username=username, password=oldpassword)
        if userinfo:
            user = User.objects.get(username=username)
            user.set_password(newpassword2)
            user.save()
            result = True