Python-day9


学习要有定位,明确目标地去学习。坚持下去,就会有所收获---leaves。(ps:现在思路已经稍微清晰点了,加油,时间不等人!!)


python08 -- 登录模块,Session以及初识jQuery


一、登录模块


1.1 登录模块MVC思路讲解

    I:前端html

    a.登录页面首次默认GET方式,返回一个待填写的表单;

    b.输入用户名密码后,点击表单按钮以POST方式向逻辑端发起请求,并把表单数据传递给逻辑端


    II:逻辑端

    a.逻辑端判断前端发起的是POST表单提交还是GET方式。如果为GET请求,说明为第一次发起,返回对应的html即可;如果为POST请求,说明是为了提交表单数据,通过request.form获取表单数据。

    b.逻辑端查询数据库数据,判断前端传来的数据是否在数据库中存在,如果存在,表示登录成功,生成session,将用户需要的信息存入session即可,如果不存在,则跳转到登录页面重新输入用户名密码


    III:数据端

    a.对数据进行增删改查,并返回结果。


1.2 登录的代码

    login_user = dict( (k,v[0]) for k ,v in dict(request.form).items())

    ##一步高阶代码将用户名密码转换为字典


1.2.1 flask代码

@app.route('/login',methods = ["GET","POST"])
def login():
        if request.method == "GET":
                return render_template("login.html")
        if request.method == "POST":
                login_user = dict( (k,v[0]) for k ,v in dict(request.form).items())
                tmp = ["name",'password']
                all_sql = "select %s from users " %','.join(tmp)
                cur.execute(all_sql)
                res = cur.fetchall()
                all_user = [ dict((v,row[k]) for k ,v in enumerate(tmp)) for row in res]
                #all_user==>[{'password': u'aa', 'name': u'KK'}, {'password': u'123456', 'name': u'TT'}, {'password': u'XX123as', 'name': u'XX'}, {'password': u'123as', 'name': u'Xman'}, {'password': u'123VV', 'name': u'AA'}]
                userName = [ x['name'] for x in all_user]
                if not login_user['name'] or not login_user['password']:
                        errmsg = "Name or Password not Null"
                        return render_template("login.html",result = errmsg)
                if  login_user['name'] not in userName:
                                                                                                    39,2-16       15%
                        errmsg = "Name is not exit"
                        return render_template("login.html",result = errmsg)
                else :

                        password = [ x['password'] for x in all_user if x['name'] == login_user['name']][0]
                        if  login_user['password'] != password:
                                errmsg = "Password is not exist "
                                return render_template("login.html",result = errmsg)
                        #return render_template("login.html",result = 'login Success')
                        else:
                                session['name'] = login_user['name']
                                return redirect('/user/userlist')


1.2.2 前端html代码

[root@xiaowei blog]# cat templates/login.html
<html>
<head>
<meta charset='utf-8'>
<title>login</title>
</head>
<body>
<table>
<form action='/login' method="POST">
	<tr><td>Name<input id ="name"  type='text' name='name'> </td></tr>
	<tr><td>Password<input id ="password" type='password' name='password'> </td></tr>
	<tr><td><input id ="loginbtn" type='submit' value='login'></td></tr>
	</form>
	
	{% if result %}
	
	<div style = "color:red">
	{{ result }}
	</div><!--定义div标签使报错信息为红色-->
	{% endif %}<!--判断是否存在报错信息-->
</table>


1.2.3 登录功能演示

    情况一:用户名密码都为空

wKioL1hsbCeRKQLqAAAVjBeUxhc241.png

    

    情况二:用户名不存在

wKioL1hsbjCQitA7AAAWpHhwT5M081.png


    情况三:密码不正确

    wKioL1hsblbDA1sPAAAV8gT8RW8461.png

    

    情况四:用户名密码正确,跳转用户列表界面

    wKioL1hsbp6hIf6BAADVTgFWAs4824.png

1.3 登录注意事项

    判断用户名密码时优先使用get(方法)。

    if not login_user['name'] or not login_user['password']: ===>更改为login_user.get('name',None)以防name字段不存在产生的报错终止程序运行


二、Session讲解


2.1 session定义

  session就是一个全局的字典,在整个flask页面中都能调用,一般在登录成功后生成session。session[key] = value。举例说明:整个flask页面就相当于一家大公司有很多栋楼,每个楼层都有门卫,Session就是第一个门卫给你发的一个通行证,带着这个通行证就能各个楼层转了。


2.2 为什么需要session

    session的主要作用是状态保持,http请求是无状态的。(从第一个门进去之后,每个门卫都是不可能都认识你,所以每次都要询问你下)


2.3 Session的工作流程

    1.登录成功生成session,用户带着session(通行证)去各个页面

    2.各个页面都有个门卫,专门检查session(通行证),有则放行。

    3.出门的时候就会收回通行证


2.4 session的主要功能

    1.创建session

    2.删除session

    3.验证

        3.1 验证用户是否登录,如果没有登录则跳转回登录页面

        3.2 验证权限、验证角色。不同的角色操作不同的方法。


2.5 session实现思路

    1.用户登录后在全局大字典session里面加一个值

    eg:session['name'] = 'wd',这个全局大字典在逻辑端任何地方都可以调用

    

    2.每个增删改查操作前,都判断下session里面有没有name这个字段值,如果有就表示已经登录;没有就表示未登录,跳转到登录页面。


2.6 session操作实例

    1.导入session

    from flask import session 

    app.secret_key = "asdasd!@#" #给加密字符串赋值


    2.session赋值

    session就是一个全局的字典,在整个flask页面中都能调用,一般在登录成功之后生成session.session[key] = value 

    本片中登录模块Session赋值为session['name'] = login_user['name']

    

    3.session 验证

    登录成功后,其他所有的操作都必须基于session认证后实现。即session存在,允许操作;否则,跳转回登录界面。

    本例中session验证为在其他监听路由下添加以下代码:

        if not session.get('name',None):

                return redirect('/login')

    4.session注销

    session注销有两种方式

    1.根据时间,生成session是带上时间参数,对比时间过期,session自动注销。(目前了解,暂无实现思路)

    2.手动注销Session

    新建loginout路由,手动注销session

@app.route('/loginout')
def loginout():
        session.pop('name')
        return redirect('/login')


2.7 session的效果图

    1.session不存在的话,任何增删改查操作都会跳转回登录页面

wKiom1hsepOAVKFWAABj4F5Kt_4520.png

    2.session存在的情况下,可以进行任意跳转,进入任何路由

wKiom1hsewmCWZC7AAFmj3sHIX8305.png


wKiom1hse6yhPHY7AACg2McwYUc269.png


三、初识jQuery

3.1 jQuery定义

    jQuery是一个"写的更少,但是做的更多"的轻量级JavaScript库。包含内容为:

    HTML元素选取

    HTML元素操作

    CSS操作

    HTML事件函数

    JavaScript特效和动画

    HTML DOM遍历和修改

    AJAX

    


3.2 jQuery准备工作

    1.在项目目录中创建static/js目录 ==>mkdir -p static/js


    2.下载jQuery插件 ==> wget https://code.jquery.com/jquery-3.1.0.min.js


     3. 检查目录结构为:     

    [root@xiaowei ketang]# tree  static/

    static/

    └── js

       └── jquery-3.1.0.min.js


3.3 jQuery三步走

    jQuery格式: $selector().action()

    

    1. $ 美元符,表示jQuery

    2. selector 选择器(选定HTML元素),这个是重点。很多种选择方式,id等

    3. action()选定后对这个元素的操作


    jQuery的基本三步走策略:

    I:选择器--找到需要操作的元素


    II:操作 -- DOM元素进行增删改查

        2.1 操作HTML文档内容--常用元素table、form、 div

        2.2 操作HTML元素属性 ---常见属性

        2.3 操作HTML元素式样 ---CSS(其实也属于属性)


    III:事件---什么情况下触发jQuery的操作,ajax等


3.4 第一个jQuery程序

    在login.html中添加以下内容

<script src = "/static/js/jquery-3.1.0.min.js"></script> #定义js文件内容
<script>
alert('di yi ge jQuery')

</script>


    执行效果截图:

wKioL1hsiD3AeCQUAAIL3s_YvCc035.png

3.5 jQuery实现对HTML元素的操作

    jQuery实现对HTML元素进行取值,在login.html文件中将form及其内部标签添加id元素。具体html代码如下

    

    jQuery选择器之ID:是html元素的唯一标识,同一个页面中不能出现重名的idName


<html>
<head>
<meta charset='utf-8'>
<title>login</title>
</head>
<body>
<table>
<!--<form action='/login' method="POST">-->
<form id="loginForm">
        <tr><td>Name<input id ="name"  type='text' name='name'> </td></tr>
        <tr><td>Password<input id ="password" type='password' name='password'> </td></tr>
        <tr><td><input id ="loginbtn" type='submit' value='login'></td></tr>
        </form>
        {% if result %}
        <div style = "color:red">
        {{ result }}
        </div>
        {% endif %}
<script src = "/static/js/jquery-3.1.0.min.js"></script>
<script>
alert('di yi ge jQuery')

</script>
</table>


    验证:运行程序,在login.html界面中输入用户名密码,在console中输入以下命令看能否获取值。ps:form标签的id值为 loginForm,input标签中用户名密码的id分别为name和password。也可以通过id值对html元素值进行修改。$('#loginForm').serialize()执行结果为"name=nihao&password=asdfa"  可以用来拼接html的url.


    

    jQuery中对数据的操作

    1.val()  操作表单数据

    2.html()  操作元素

    3.attr()  操作属性

$('#loginForm').serialize()
"name=aaaa&password=dddd"
$('#loginForm').serialize()
"name=aaaa&password=dddd"
$('#name').val()
"aaaa"
$('#password').val()
"dddd"

    通过id修改元素值

wKiom1hsmC-Qu4ElAADBv8HKDz8714.png


3.6 jQuery实现登录模块

    jQuery实现登录需要注意的知识点:

    1.flask逻辑端return 返回字典类型数据:eg : return json.dumps({'code':0,'result': "login success "}) ,对应的需要import json模块。


    2.html中script标签内的回调函数。要jQuery代码逻辑。


3.6.1 jQuery实现登录的前后端代码:

##flask逻辑端代码(仅登录模块)
##注意在开始要import json

@app.route('/login',methods = ["GET","POST"])
def login():
        if request.method == "GET":
                return render_template("login.html")
        if request.method == "POST":
                data = dict( (k,v[0]) for k ,v in dict(request.form).items())
                tmp = ["name",'password']
                all_sql = "select %s from users " %','.join(tmp)
                cur.execute(all_sql)
                res = cur.fetchall()
                all_user = [ dict((v,row[k]) for k ,v in enumerate(tmp)) for row in res]
                #all_user==>[{'password': u'aa', 'name': u'KK'}, {'password': u'123456', 'name': u'TT'}, {'password': u'XX123as', 'name': u'XX'}, {'password': u'123as', 'name': u'Xman'}, {'password': u'123VV', 'name': u'AA'}]
                userName = [ x['name'] for x in all_user]
                if not data.get('name',None)  or not data.get('password',None):
                        errmsg = "Name or Password not Null"
                        #return render_template("login.html",result = errmsg)
                        return json.dumps({'code':1,'result': errmsg})
                if  data.get('name',None) not in userName:
                        errmsg = "Name is not exit"
                        #return render_template("login.html",result = errmsg)
                        return json.dumps({'code':1,'result': errmsg})
                else :

                        password = [ x['password'] for x in all_user if x['name'] == data['name']][0]
                        if  data.get('password',None) != password:
                                errmsg = "Password is not exist "
                                #return render_template("login.html",result = errmsg)
                                return json.dumps({'code':1,'result': errmsg})
                        #return render_template("login.html",result = 'login Success')
                        else:
                                session['name'] = data['name']
                                #return redirect('/user/userlist')
                                return json.dumps({'code':0,'result': "login success "})
                                
##login.html前端HTML中代码
<html>  
<head>  
<meta charset='utf-8'>
<title>login</title>
</head>
<body>
<table>
<!--<form action='/login' method="POST">-->
<form id="loginForm">
        <tr><td>Name<input id ="name"  type='text' name='name'> </td></tr>
        <tr><td>Password<input id ="password" type='password' name='password'> </td></tr>
        <tr><td><input id ="loginbtn" type='submit' value='login'></td></tr>
        </form>
        {% if result %}
        <div style = "color:red">
        {{ result }}
        </div>
        {% endif %}
<script src = "/static/js/jquery-3.1.0.min.js"></script>
<script>
//alert('di yi ge jQuery') <!--Test jQuery-->
$('#loginbtn').on('click',function(){
        var str = $('#loginForm').serialize()
        console.log(str)
        $.post('/login',str,function(data){   //回调函数,注意function(data)中data参数不能丢
                console.log(data)
                data = JSON.parse(data)
                console.log(data)
                if (data['code'] == 0){
                        alert(data['result'])
                        location.href='/user/userlist'
                }else{
                        $('errmsg').html(data['errmsg'])
                }
        })
        return  false 

})

</script>
</body>
</table>


3.6.2 jQuery登录效果截图

    1.错误信息截图

wKiom1hsqsuDEHzkAADqI-Fj3Z8554.png


   2.正常登录效果图(点击确认后跳转到userlist界面)

wKiom1hsqzjwoXCaAAE2tHVCgFU714.png

wKioL1hsq5OgeA1XAAIG4U4vHkE343.png-wh_50


3.6.2 jQuery实现登录重点

    回调函数:function(data为回调函数)(ps:flask 端代码无需更改,只是将html中事件响应更改为jQuery。)

##login.html

<script>

//alert('di yi ge jQuery') <!--Test jQuery-->

$('#loginbtn').on('click',function(){

        var str = $('#loginForm').serialize()

        console.log(str) ##实现记录$('#loginForm').serialize()的值

        $.post('/login',str,function(data){

                console.log(data)

                data = JSON.parse(data)

                console.log(data)

                if (data['code'] == 0){

                        alert(data['result']) #事件触发以及展示信息

                        location.href='/user/userlist' ##事件完成后跳转到用户列表

                }else{

                       // $('errmsg').html(data['errmsg']) #console窗口打印$('#loginForm').serialize()内容

                       //以下更改使得报错信息也在jQuery弹框中显示。

                   alert(data['result'])

                        location.href='/login'



                }

        })

        return  false 


})


</script>







四、其他注意事项及知识点:

    1.对数据库的操作,try except 方便排错


     2.flask代码组织结构有两种方式      包 + 蓝图


       3.session后期可以通过使用装饰器来包装