Flask实现用户登录、注册和分页显示用户信息页面

基于Flask实现一个更加美观的用户登录界面,包括登录,注册,消息闪现,模板继承,文件包含以及Jinja2语法。

1、创建一个Flask项目:
Flask实现用户登录、注册和分页显示用户信息页面_第1张图片
通常我们将html文件放在templates文件夹中,将静态文件,比如css文件,js文件,字体,图片放在static文件夹中。

2、主程序app.py

from flask import Flask, request, render_template, redirect, session, flash

# from Flask.UserManager.utils.is_login import is_login
# from UserManager.utils.is_login import is_login
from utils.is_login import is_login

app = Flask(__name__)

# flash的消息都存储在session,需要一个会话密匙,密匙随便输入就行,如果对保密性要求高的话,可以使用相关的密匙生成函数
app.config["SECRET_KEY"] = "westos"  # 加密盐

users = [
    {
        'username':'root',
        'password':'root'
    }
]
# 会话: session
# 缓存: cookie

@app.route('/bbs/')
@is_login
def bbs():
    return 'bbs'

@app.route('/blog/')
@is_login
def blog():
    return 'blog'

@app.route('/')
def index():
    return render_template('index.html')


@app.route('/login/', methods=['GET', 'POST'])
def login():
    # get直接读取填写的数据
    if request.method == 'GET':
        return  render_template('login.html')
    # request.method=='POST
    else:
        # 获取post提交的数据
        username = request.form.get('username')
        password = request.form.get('password')
        for user in users:
            if user['username'] == username and user['password'] == password:
                # 存储用户登录信息; session可以认为时字典对象
                session['username'] = username
                # print(session)
                flash("登录成功")
                return redirect('/')
        else:
            flash("登录失败",category='error')
            return render_template('login.html', errMessages='login fail')

@app.route('/logout/')
def logout():
    # 将session中的用户信息删除;
    session.pop('username')
    flash("注销成功")
    return  redirect('/login/')

@app.route('/register/', methods=['GET', 'POST'])
def register():
    """
    1), http请求的方法为get方法, 直接返回注册页面;
    2). http请求的方法为post方法,
        - 注册的用户名是否已经存在, 如果存在, 重新注册;
        - 如果不存在, 存储用户名和密码到数据库中;
    """
    if request.method == 'GET':
        return  render_template('register.html')
    else:
        # 获取post提交的数据
        username = request.form.get('username')
        password = request.form.get('password')
        for user in users:
            # 注册的用户名是否已经存在, 如果存在, 重新注册;
            if user['username'] == username:
                flash("注册失败: 用户名冲突")
                # session['username'] = username
                return redirect('/register/')
        # 如果不存在, 存储用户名和密码到数据库中;
        else:
            users.append(dict(username=username, password=password))
            flash("用户注册成功, 请登录")
            return  redirect('/login/')

@app.route('/list//') # 用户信息的分页查看
def list(page):
    return  render_template('list.html', users=users)


if __name__ == '__main__':
    app.run(port=5006)

3、写完主程序之后,在来写html页面:

首先是login.html文件

<!DOCTYPE html>
<html lang="en">
<head>
<title>登录页面</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 {##}
<link href="../static/css/login.css" rel="stylesheet" type="text/css" media="all" />

</head>
<body>

	<!-- main -->
	<div class="main-w3layouts wrapper">
		<div class="main-agileinfo">
			<div class="agileits-top">
				<form action="/login/" method="post">
                    <!-- required="":用户名不能为空  -->
					<input class="text" type="text" name="username" placeholder="用户名" required="">
					<input class="text" type="password" name="password" placeholder="密码" required="">
					<div class="wthree-text">
						<ul>
							<li>
								<label class="anim">
									<input type="checkbox" class="checkbox" >
									<span> 记住 ?</span>
								</label>
							</li>
							<li><a href="#">忘记密码 ?</a> </li>
						</ul>
						<div class="clear"> </div>
					</div>
					<input type="submit" value="登录">
                    {% for msg in get_flashed_messages() %}
                        <p style="color: red;">{{ msg }}</p>
                    {% endfor %}
				</form>
				<p>创建一个账号? <a href="/register/"> 立即注册!</a></p>
			</div>
		</div>

		<div class="w3copyright-agile">
			<p>© 2020 西部开源</p>
		</div>

		<ul class="w3lsg-bubbles">
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
		</ul>
	</div>
	<!-- //main -->

</body>
</html>

闪现消息的创建和接收: 在主程序中flash(message)—>在html文档中{{ get_flashed_message }}接收闪现消息。flash的消息都存储在session,需要一个会话密匙,密匙随便输入就行。

注册页面:register.html
注册页面在登陆页面的基础上稍加改正。

<!DOCTYPE html>
<html>
<head>
    <title>注册页面</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    {#    两种方式任选一种 #}
    {##}
    <link href="{{ url_for('static', filename='css/login.css') }}" rel="stylesheet" type="text/css" media="all"/>

</head>
<body>

<!-- main -->
<div class="main-w3layouts wrapper">
    <div class="main-agileinfo">
        <div class="agileits-top">
            <form action="/register/" method="post">
                <input class="text" type="text" name="username" placeholder="用户名" required="">
                <input class="text" type="password" name="password" placeholder="密码" required="">
                <div class="wthree-text">
                    <ul>
                        {#							
  • #} {# {# #} {# 记住 ? #} {# #} {#
  • #}
    <li><a href="#">忘记密码 ?</a></li> </ul> <div class="clear"></div> </div> <input type="submit" value="注册"> {% for msg in get_flashed_messages() %} <P style="color: red">{{ msg }}</P> {% endfor %} </form> <p>已有账号? <a href="/login/"> 立即登录!</a></p> </div> </div> <!-- copyright --> <div class="w3copyright-agile"> <p>© 2020 西部开源</p> </div> <!-- //copyright --> <ul class="w3lsg-bubbles"> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> </div> <!-- //main --> </body> </html>

    效果如图:
    Flask实现用户登录、注册和分页显示用户信息页面_第2张图片
    分页显示用户信息–list.html

    {% extends 'base.html' %}
    
    
    {% block title %} 用户列表{% endblock %}
    
    
    {% block body %}
        <h1>用户信息</h1>
        <table width="80%" align="center" style="margin-top: 50px">
            <tr>
                <td>用户名</td>
                <td>密码</td>
            </tr>
            {% for user in users %}
                <tr>
                    <td>{{ user.username }}</td>
                    <td>{{ user.password }}</td>
                </tr>
    
    
            {% endfor %}
    
    
        </table>
    
    {% endblock %}
    

    list.html继承了base.html,base.html文件如下

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% block title %} {% endblock %}</title>
        {#    #}
        <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}">
        <link rel="stylesheet" href="../static/css/weibo.css">
        <script src="../static/js/jquery-3.1.0.js"></script>
        <script src="../static/js/bootstrap.min.js"></script>
        <script src="../static/js/weibo.js"></script>
    </head>
    <body>
    
    <!--
    一个典型导航条的结构如下:
        nav.navbar.navbar-default
            .container
                .nav-header
                    a.nav-brand
    nav:
        .navbar-fixed-top:固定在顶部
        .navbar-fixed-bottom:固定在底部
        . navbar-static-top: 不是固定在页面顶部的,会随页面下拉消失。
    container:用于支持响应式布局的容器
        .container: fixed-with
        .container-fluid: full-width
    -->
    <nav class="navbar navbar-fixed-top" style="background: #e0620d ;padding-top: 3px;height:50px; ">
        <div class="container-fluid" style="background: #fff;">
            <div class="navbar-header">
                <span class="navbar-brand" href="#"> WEIBO</span>
                <button type="button" class="navbar-toggle" data-toggle="collaspe" data-target="#my-navbar-collapse">
                    <span class="sr-only">切换导航</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
    
                </button>
            </div>
            <form class="navbar-form navbar-left" role="search">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="#热门话题#">
                    <span class="glyphicon glyphicon-search btn_search"></span>
                    <!--<button type="submit" class="btn btn-default">提交</button>-->
                </div>
    
            </form>
    
            <div class="collapse navbar-collapse" id="my-navbar-collapse">
    
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#"><i class="glyphicon glyphicon-user"></i>&nbsp;&nbsp;{{ session.username }}</a></li>
    
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            设置 <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
    
                            {#
                                    1. 如何让判断用户是否登录?
                                    session是否存在用户信息===session.get('username')
    
                                    如果用户登录, 则显示注销;
                                    如果用户没有登录, 则显示登录和注册;
    
    
                                #}
                            {% if session.get('username') %}
                                <li><a href="/logout/">注销</a></li>
    
                            {% else %}
                                <li><a href="/login/">登录</a></li>
                                <li><a href="/register/">注册</a></li>
    
                            {% endif %}
    
    
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
        <hr style="margin: 0;padding: 0;color:#222;width: 100%">
    </nav>
    
    
    {% block body %}
    
    
    {% endblock %}
    
    
    </body>
    </html>
    

    主页样式–index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>weibo</title>
        {#    #}
        <link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}">
        <link rel="stylesheet" href="../static/css/weibo.css">
        <script src="../static/js/jquery-3.1.0.js"></script>
        <script src="../static/js/bootstrap.min.js"></script>
        <script src="../static/js/weibo.js"></script>
    </head>
    <body>
    
    <!--
    一个典型导航条的结构如下:
        nav.navbar.navbar-default
            .container
                .nav-header
                    a.nav-brand
    nav:
        .navbar-fixed-top:固定在顶部
        .navbar-fixed-bottom:固定在底部
        . navbar-static-top: 不是固定在页面顶部的,会随页面下拉消失。
    container:用于支持响应式布局的容器
        .container: fixed-with
        .container-fluid: full-width
    -->
    <nav class="navbar navbar-fixed-top" style="background: #e0620d ;padding-top: 3px;height:50px; ">
        <div class="container-fluid" style="background: #fff;">
            <div class="navbar-header">
                <span class="navbar-brand" href="#"> WEIBO</span>
                <button type="button" class="navbar-toggle" data-toggle="collaspe" data-target="#my-navbar-collapse">
                    <span class="sr-only">切换导航</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
    
                </button>
            </div>
            <form class="navbar-form navbar-left" role="search">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="#热门话题#">
                    <span class="glyphicon glyphicon-search btn_search"></span>
                    <!--<button type="submit" class="btn btn-default">提交</button>-->
                </div>
    
            </form>
    
            <div class="collapse navbar-collapse" id="my-navbar-collapse">
    
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="#"><i class="glyphicon glyphicon-user"></i>&nbsp;&nbsp;{{ session.username }}</a></li>
    
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">
                            设置 <b class="caret"></b>
                        </a>
                        <ul class="dropdown-menu">
    
                            {#
                                    1. 如何让判断用户是否登录?
                                    session是否存在用户信息===session.get('username')
    
                                    如果用户登录, 则显示注销;
                                    如果用户没有登录, 则显示登录和注册;
    
    
                                #}
    
                            {% if session.get('username') %}
                                <li><a href="/logout/">注销</a></li>
    
                            {% else %}
                                <li><a href="/login/">登录</a></li>
                                <li><a href="/register/">注册</a></li>
    
                            {% endif %}
    
    
                        </ul>
                    </li>
                </ul>
            </div>
        </div>
        <hr style="margin: 0;padding: 0;color:#222;width: 100%">
    </nav>
    
    
    <!--
    content:
        1.
        2.
    -->
    <p style="color: red;">{{ get_flashed_messages() }}</p>
    <div class="container container-bg">
        <div class="row">
            <div class="col-sm-2"></div>
            <div class="col-sm-6 col-xs-12 my_edit">
                <div class="row" id="edit_form">
                    <span class="pull-left" style="margin: 15px">编写新鲜事 </span>
                    <span class="tips pull-right" style="margin:15px;"></span>
                    <form role="form" style="margin-top: 50px;">
                        <!--message-->
                        <div class="col-sm-12">
                            <div contentEditable="true" id="content" class="form-control"></div>
                        </div>
                        <!--other: image and emjo-->
                        <div class="col-sm-12" style="margin-top: 12px;">
                            <span class="emoji">表情</span>
                            <span class="pic" class="imgPath">图片</span>
    
                            <span>
                            <input type="file" name="" class="select_Img" style="display: none">
                                <!--<img class="preview" src="">-->
                            </span>
    
    
                            <div class="myEmoji">
                                <ul id="myTab" class="nav nav-tabs">
                                    <li class="active">
                                        <a href="#set" data-toggle="tab">
                                            预设
                                        </a>
                                    </li>
                                    <li><a href="#hot" data-toggle="tab">热门</a></li>
                                </ul>
                                <div id="myTabContent" class="tab-content">
                                    <div class="tab-pane fade in active" id="set">
                                        <div class="emoji_1"></div>
    
                                    </div>
                                    <div class="tab-pane fade" id="hot">
                                        <div class="emoji_2"></div>
                                    </div>
    
                                </div>
                            </div>
    
    
                            <button type="button" id="send" class="btn btn-default pull-right disabled">发布</button>
    
                        </div>
                    </form>
    
                </div>
    
    
                <!-- message list-->
                <div class="row item_msg">
                    <div class="col-sm-12 col-xs-12 message">
                        <img src="../static/img/icon.png" class="col-sm-2 col-xs-2" style="border-radius: 50%">
                        <div class="col-sm-10 col-xs-10">
                            {#   获取缓存中的用户名信息, session, request, g, get_flashed_messages()可以直接从前台获取后台信息                        #}
                            <span style="font-weight: bold;">{{ session.username }}</span>
                            <br>
                            <small class="date" style="color:#999">1分钟前</small>
                            <div class="msg_content">happy day!
                                <img class="mypic" src="../static/img/bg_1.jpg">
                            </div>
    
                        </div>
    
                    </div>
    
    
                </div>
            </div>
    
    
            <!--right content-->
    
            <div class="col-sm-3 col-xs-12 part_right">
                <div class="row text-center inform">
                    <img src="../static/img/icon.png">
                    <h4 style="font-weight: bold;">Westos</h4>
                    <div class="col-sm-12 my_inform">
                        <div class="col-sm-4 col-xs-4">
                            <div>111</div>
                            <div class="sort">关注</div>
    
                        </div>
                        <div class="col-sm-4 col-xs-4">
                            <div>111</div>
                            <div class="sort">粉丝</div>
                        </div>
                        <div class="col-sm-4 col-xs-4">
                            <div>111</div>
                            <div class="sort">博客</div>
                        </div>
                    </div>
                </div>
                <div class="row part_hot">
                    <div class="col-sm-12">
                        <span class="pull-left" style="padding: 10px;font-size:16px;font-weight: bold;">热门话题</span>
                        <span class="pull-right" style="padding: 10px;">换话题</span>
    
                    </div>
    
    
                    <div class="col-sm-12 item_hot">
                        <span class="pull-left">#英雄联盟s7#
                        <span class="pull-right item_num">34.6亿</span>
                    </div>
    
                    <div class="col-sm-12 item_hot">
                        <span class="pull-left">#今天霜降#
                        <span class="pull-right item_num">2.6亿</span>
                    </div>
    
                    <div class="col-sm-12 item_hot">
                        <span class="pull-left">#亚洲新歌榜#
                        <span class="pull-right item_num">10.4亿</span>
                    </div>
    
                    <div class="col-sm-12 item_hot">
                        <span class="pull-left">#扑通扑通少女心#
                        <span class="pull-right item_num">1.5亿</span>
                    </div>
    
                    <div class="col-sm-12 item_hot">
                        <span class="pull-left">#突然开心#
                        <span class="pull-right item_num">1.1亿</span>
                    </div>
                    <hr style="margin: 0;padding: 0;width: 100%">
    
                    <div class="col-sm-12 text-center" style="padding: 10px"><a href="#">查看更多</a></div>
    
                </div>
    
            </div>
    
        </div>
    
    
    </div>
    
    
    <script type="text/javascript">
        $(function () {
    
            //*************************1. content set ************************************
            $('#content').keyup(function () {
                var content_len = $('#content').text().replace(/\s/g, "").length;
                $('.tips').text("已经输入" + content_len + "个字");
    
                if (content_len === 0) {
                    $('.tips').text("");
                    $('#send').addClass('disabled');
                    return false;
                } else {
                    $('#send').removeClass('disabled');
                }
    
            });
    
            //*****************************************2. pic set *************************************
            $(".pic").click(function () {
                $(".select_Img").click();
    
    
            });
    
    
            //*****************************************3. send set ****************************************
    
            $("#send").click(function () {
                //判断选择的是否是图片格式
                var imgPath = $(".select_Img").val();
                var start = imgPath.lastIndexOf(".");
                var postfix = imgPath.substring(start, imgPath.length).toUpperCase();
                var content = $('#content').html();
                if (imgPath != "") {
    
                    if (postfix != ".PNG" && postfix != ".JPG" && postfix != ".GIF" && postfix != ".JPEG") {
                        alert("图片格式需为png,gif,jpeg,jpg格式");
                    } else {
                        var uploadImg = "';
                        $(".item_msg").append("
    Westos
    刚刚
    " + content + "
    "
    ); } } else { $(".item_msg").append("
    Westos
    刚刚
    " + content + "
    "
    ); } }); //添加表情包1 for (var i = 1; i < 60; i++) { $(".emoji_1").append(""); } //添加表情包2 for (var i = 1; i < 61; i++) { $(".emoji_2").append(""); } $(".emoji").click(function () { $(".myEmoji").show(); //点击空白处隐藏弹出层 $(document).click(function (event) { //is 判断点击位置是否在目标区域内,如果不在,则返回false;否则true //has 用来判断点击的位置是否在目标区域的子元素上 if (!$("#edit_form").is(event.target) && $("#edit_form").has(event.target).length === 0) { $(".myEmoji").hide(); } }); }); //将表情添加到输入框 // each() 方法规定为每个匹配元素规定运行的函数。 $(".myEmoji img").each(function () { $(this).click(function () { var url = $(this)[0].src; $('#content').append(""); $("#send").removeClass("disabled"); }) }); //放大或缩小预览图片 $(".mypic").click(function () { var oWidth = $(this).width(); //取得图片的实际宽度 var oHeight = $(this).height(); //取得图片的实际高度 if ($(this).height() != 200) { $(this).height(200); } else { $(this).height(oHeight + 200 / oWidth * oHeight); } }) }); </script> </body> </html>

    主页样式如图:
    Flask实现用户登录、注册和分页显示用户信息页面_第3张图片
    用户登录之后的显示界面如下:
    Flask实现用户登录、注册和分页显示用户信息页面_第4张图片

    完整代码可访问:https://github.com/wtwdy/UserManager–,包括相关js和css文件。

    你可能感兴趣的:(Flask,Python)