赞
踩
当用户使用浏览器访问网站的页面信息时,会有如下的经历:
当用户通过浏览器提交一个请求时,首先将请求提交给NGINX服务器,然后经过中间人uWSGI转换协议,使请求能够提交给使用不同协议的Flask等,并进行处理,处理结束后再原路返回,将请求结果返回给用户。
其中:
Flask是一个Web框架, 就是提供一个工具库和技术来允许你构建一个Web应用程序.这个Web应用程序可以是一些Web页面,博客, wiki ,基于 Web 的日历应用或商业网站。
Flask依赖模块(还有一些别的,这里介绍一个):
web服务网关接口(Web Server Gateway Interface,缩写为WSGI
Flask属于微框架( micro-framework )这一类别,微架构通常是很小的不依赖外部库的框架(安装时不会下载一些附带的依赖包,根据你实际使用的情况自己下载需要的包)。
两个名词:
路由:
@app.route('') #根据选择的路径,判断采用哪个试图函数
视图函数:
def 函数名():#视图函数(函数名一定不能重复):给用户返回查看的页面信息
代码:
from flask import Flask # __name__确定此flask项目的所在位置 app=Flask(__name__) # 实现首页:http://172.25.254.1:9999/(访问首页) @app.route('/') #路由:根据选择的路径,判断采用哪个试图函数 def index(): #视图函数(函数名一定不能重复):给用户返回查看的页面信息 return '这是网站的首页' @app.route('/login/') def login(): return '正在登录。。' @app.route('/logout') def logout(): return '正在登出。。。' if __name__ == '__main__': #运行flask项目,默认IP和端口为127.0.0.1,5000 # 如何特色化指定IP和端口:host='0.0.0.0'指开放本机的所有ip ,port=5000必须是整型 # debug=True开启调试模式(在测试环境中开启,生产环境一定要关闭) app.run(host='192.168.1.111',port=9998,debug=True)
注意:
在windows系统中,IP地址需要改成自己本地主机的IP;
通过ipconfig查询
""" http://www.csdn.org/1200 http://www.csdn.org/1202 http://www.csdn.org/1203 http://www.csdn.org/1204 动态路由:http://csdn.org/<userid> """ from flask import Flask,request app=Flask(__name__) @app.route('/<int:userid>') def useridinfo(userid): return '正在查看用户%s的详细博客。。。'%(userid) @app.route('/welcom/<string:username>') def welcom(username): return '欢迎访问%s用户的主页'%(username) """ http://movie.douban.com/top250?start=254filter= """ #request 存储用户请求页面的所有头部信息 @app.route('/top250') def top250(): users=['user%s'%(i) for i in range(100)] print('客户端的用户代理:',request.user_agent)#返回客户端的用户代理 print('请求页面的头部信息',request.headers) print('客户端的IP地址',request.remote_addr) print('客户端请求的参数详细信息',request.args) print('客户端http请求的方法',request.method)#http请求方法 get:会在地址栏显示 #获取用户请求的URRL地址里的key值对应的value值 start=int(request.args.get('start'))#返回的是字符串,转化为整型 user=request.args.get('user') return 'top250 显示数据:%s条 用户名:%s'%(start,user) import json return json.dumps(users[start:start + 10]) # 返回的是列表,转为字符串 if __name__ == '__main__': app.run(host='192.168.1.111',port=9999,debug=True)
运行结果:
return ‘top250 显示数据:%s条 用户名:%s’%(start,user) 执行的结果;
客户端的用户代理: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko Core/1.70.3706.400 SLBrowser/10.0.3974.400
请求页面的头部信息 Accept: text/html, application/xhtml+xml, image/jxr, */*
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
Host: 192.168.1.111:9999
Connection: Keep-Alive
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko Core/1.70.3706.400 SLBrowser/10.0.3974.400
客户端的IP地址 192.168.1.111
客户端请求的参数详细信息 ImmutableMultiDict([('start', '22'), ('user', 'anan')])
客户端http请求的方法 GET
return json.dumps(users[start:start + 10]) 执行的结果‘
提交查询信息或者信息不重要时,使用get
例如:hello {{name}}【请求的用户名不同,hello后面跟的内容不一样】
如果若用户返回的信息为:name = westos
就将name=westos填入 —> hello westos
这个过程就叫做模板渲染。
flask和django一样都配备了Jinja2模板引擎,可以使用 render_template() 方法来渲染模板.
重定向:
错误:
http状态码即HTTP请求中出现的错误:404 200 304 302 500 |
4开头 客户端错误 |
5开头 服务端错误 |
代码:
from flask import Flask,render_template,request,redirect app=Flask(__name__) @app.route('/') def index(): return '<h1>主页</h1>' @app.route('/login/') def login(): """ 一般情况下,不会直接把HTML文件内容直接返回 而是将HTML文件保存到当前的templates目录中[templates目录一般必须写为这个名字] 通过render_template方法调用; 默认情况下,flask在程序文件夹中的templates子文件中寻找模板 """ return render_template('login.html') #返回了login.html,在这个页面中,用户输入了登录信息后,提交到action='/login2/' #通过login2函数来判断用户名和密码 #处理登录逻辑,判断用户名和密码 @app.route('/login2/') def login2(): #获取用户输入的用户名 username=request.args.get('username',None) password=request.args.get('password',None) #逻辑处理,判断用户名和密码是否正确 if username=='root' and password=='anan': #重定向到指定路由 #如果登陆成功,进入主页 return redirect('/') else: #如果登录失败,重定向到登陆界面,重新登录 return redirect('/login/') if __name__ == '__main__': app.run(host='192.168.1.111',port=9992,debug=True)
得到的第一个页面
第二个页面
当输入的用户名和密码正确时,页面跳转至第一个页面;
输入的用户名或密码不正确时,页面跳转至第二个页面。
代码
from flask import Flask,render_template,request,redirect app=Flask(__name__) @app.route('/') def index(): return '<h1>主页</h1>' #默认路由只支持get方法,如何指定接受post方法? @app.route('/login/',methods=['GET','POST']) def login(): """ 1.用户访问网址:http://xxxx/login/,返回登录的html页面, 主页页面时通过get方法访问得到的,get是默认路由支持的提交方法 2.返回了html页面,用户填写信息 根据<form action='/login/' method='post'>提交到login,提交方法是post 3.执行post提交的逻辑 """ if request.method=='POST': # post提交的数据如何获取? request.form.get; # get提交的数据获取方法:request.args.get; #post提交的数据存放在一个表单中 print(request.form) username=request.form.get('username',None) password=request.form.get('password',None) if username=='root' and password=='anan': #如果登陆成功,重定向进入主页 return redirect('/') else: #render_templates()模板渲染,给html传递变量,传的是erro_message return render_template('login_post.html',error_message='用户名或者密码错误') else: return render_template('login_post.html') if __name__ == '__main__': app.run(host='192.168.1.111',port=9949,debug=True)
如果用户名或密码输入错误时
如果输入正确时
为什么要自定义错误页面?
如果在浏览器的地址栏中输入了不可用的路由,那么会显示一个状态码为404的错误页面
如何自定义错误页面?
像常规路由一样,flask允许程序使用基于模板的自定义错误页面 errorhandler()
最常见的错误代码有两个:
404:用户端请求位置页面或路由时显示
500:有未处理的异常时显示
代码
from flask import Flask,render_template app=Flask(__name__) @app.route('/welcom/<string:username>') def welcom(username): return render_template('welcom.html',name=username) @app.errorhandler(404) def page_not_found(e): return render_template('404.html'),404 @app.errorhandler(500) def internal_server_error(e): return render_template('500.html'),500 if __name__ == '__main__': app.run(host='192.168.1.111',port=9939,debug=True)
templates目录中的welcom.html文件:
<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>welcom</title>
</head>
<body>
<!--定义变量通过两个花括号,花括号中写变量名 -->
<h1>欢迎用户{{name }}</h1>
</body>
</html>
templates目录中的404.html文件:
<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>404</title>
</head>
<body>
<h1 style="color: chocolate">你寻找的网站迷路了。。。</h1>
</body>
</html>
templates目录中的500.html文件:
<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>500</title>
</head>
<body>
<h1 style="color: darksalmon">请耐心等待,稍后再试</h1>
</body>
</html>
from flask import Flask import logging app=Flask(__name__) #日志系统配置,设置文件存放位置 handler=logging.FileHandler('app.log',encoding='utf-8') #设置日志文件存储格式 logging_format=logging.Formatter('%(asctime)s-%(levelname)s-%(filename)s-%(funcName)s-%(lineno)s-%(message)s') #将日志文件处理对象和日志格式绑定 handler.setFormatter(logging_format) #设置日志级别 handler.setLevel('DEBUG') #将日志文件和app绑定 app.logger.addHandler(handler) @app.route('/') def index(): app.logger.debug('hello') app.logger.error('error') app.logger.exception('exception') return 'index' if __name__ == '__main__': app.run(debug=True)
app.log显示
2020-03-02 23:55:29,782-DEBUG-04_flask日志记录.py-index-26-hello
2020-03-02 23:55:29,782-ERROR-04_flask日志记录.py-index-27-error
2020-03-02 23:55:29,782-ERROR-04_flask日志记录.py-index-28-exception
NoneType: None
动态的 web 应用也需要静态文件,一般是 CSS , 图片和 JavaScript 文件。理想情况下你的服务器已经配置好了为你的提供静态文件的服务。
在开发过程中,Flask静态文件位于应用的/static目录中。
静态文件在文件系统中的位置是:static/style.css
{{ url_for(‘static’, filename = ‘style.css’)}}
session 的对象,允许你在不同请求之间储存信息。这个对象相当于用密钥签名加密的 cookie , 即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它。
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/') def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return ''' <form method="post"> <p><input type=text name=username> <p><input type=submit value=Login> </form> ''' @app.route('/logout') def logout(): # remove the username from the session if it's there session.pop('username', None) return redirect(url_for('index'))
from flask import flash
app.comfig['SECRET_KEY']='anan' #加密盐
flash('要展示的闪现信息')
{{get_flashed_messages()}}
Jinja2是一个现代的,设计者友好的,仿照Django模板的python模板语言。
它速度快,被广泛使用,并且提供了可选的模板执行环境保证安全。
{{ 变量名 / 函数调用 }}
类似于python中的一些方法
完整的过滤器查看位置:http://jinja.pocoo.org/docs/templates/#builtin-filters
常用的过滤器:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
text= """
<h1>hello world</h1>
"""
return render_template('jinja2.html', text=text)
if __name__ == '__main__':
app.run()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--safe过滤器,展示原本的html,不将它进行转义-->
{{ text | safe }}
<!--striptages把值中所有的html标签都删掉,只展示文本-->
{{ text | striptags }}
</body>
</html>
不进行转义及去标签时
第一行:用safe进行转义后
第二行:用striptags进行去标签后
{% for i in li %}
xxxx
{% endfor %}
例如:
{% for user in users%}
<tr>
<td>{{ user.username}}</td>
<td>{{ user.password}}</td>
</tr>
{% endfor%}
{% if 条件%}
xxxx
{% elif 条件%}
xxxx
{% else %}
xxxx
{% endif %}
例如:
<!--如果用户登录,显示注销-->
<!--如果没有登录,显示登录和注册-->
<!--如何判断是否登录: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 %}
可以理解为python中的函数
相当于python中定义函数def,利用关键字macro
{% macro 宏名称(参数)%}
xxxx
{% endmacro %}
{{宏名称()}}
{# 声明Jinja2的宏 #}
{% macro fun(id) %}
<h1>hello {{id}}</h1>
{% endmacro %}
{# 调用宏#}
{{ fun(1) }}
{{ fun(2) }}
{{ fun(3) }}
直接包含,将一个html文件放到另一个html文件里
{% include '文件名.html' %}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .left{ width: 20%; border: 1px solid red; float: left; } .right{ width: 79%; border: 1px solid green; float: left; } </style> </head> <body> <div class="left"> { % include 'left.html' % } </div> <div class="right"> right </div> </body> </html>
left.html文件
<ul>
<li>新闻</li>
<li>财经</li>
<li>八卦</li>
</ul>
一般网站的导航栏和底部不会变化,为了避免重复编写导航栏信息将相同的部分抽象出来,将不同的内容填充进去。
相当于占了一个位置,将来要将不同的内容填充进去
{% block 名称%}
{% endblock %}
模板文件:Jinja2_base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %} {% endblock %}</title>
</head>
<body>
<div style="width: 100px; height: 200px">这里是导航栏</div>
{% block body %}
{% endblock %}
<div style="width: 100px; height: 200px">这里是底部</div>
</body>
</html>
其中{% block title %} 和{% block body %}是要填充的部分
{% extends '模板文件.html' %}
{% block 名称 %}
要填充的内容
{% endblock %}
{% extends 'jinja2_base.html' %}
{% block title %}主页{% endblock %}
{% block body %}
{# 声明Jinja2的宏 #}
{% macro fun(id) %}
<h1>hello {{ id }}</h1>
{% endmacro %}
{#调用宏#}
{{ fun(1) }}
{{ fun(2) }}
{% endblock %}
from flask import Flask, request, render_template, redirect, session, flash app = Flask(__name__) app.config["SECRET_KEY"] = "westos" # 加密盐 users = [ { 'username':'root', 'password':'root' } ] # 会话: session # 缓存: cookie @app.route('/') def hello_world(): return render_template('index.html') @app.route('/login/', methods=['GET', 'POST']) def login(): 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("登录失败") 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/<int:page>/') # 用户信息的分页查看 def list(page): return render_template('list.html', users=users) if __name__ == '__main__': app.run(port=5000)
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>weibo</title> {# <link rel="stylesheet" href="../static/css/bootstrap.css">#} <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> {{ 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> <span class="pull-right item_num">34.6亿</span> </div> <div class="col-sm-12 item_hot"> <span class="pull-left">#今天霜降#</span> <span class="pull-right item_num">2.6亿</span> </div> <div class="col-sm-12 item_hot"> <span class="pull-left">#亚洲新歌榜#</span> <span class="pull-right item_num">10.4亿</span> </div> <div class="col-sm-12 item_hot"> <span class="pull-left">#扑通扑通少女心#</span> <span class="pull-right item_num">1.5亿</span> </div> <div class="col-sm-12 item_hot"> <span class="pull-left">#突然开心#</span> <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 = "<img class='mypic' src='../img/" + imgPath + '>'; $(".item_msg").append("<div class='col-sm-12 col-xs-12 message' > <img src='img/icon.png' class='col-sm-2 col-xs-2' style='border-radius: 50%'><div class='col-sm-10 col-xs-10'><span style='font-weight: bold;''>Westos</span> <br><small class='date' style='color:#999'>刚刚</small><div class='msg_content'>" + content + "<img class='mypic' οnerrοr='this.src='img/bg_1.jpg' src='img/" + imgPath + "' ></div></div></div>"); } } else { $(".item_msg").append("<div class='col-sm-12 col-xs-12 message' > <img src='img/icon.png' class='col-sm-2 col-xs-2' style='border-radius: 50%'><div class='col-sm-10 col-xs-10'><span style='font-weight: bold;''>Westos</span> <br><small class='date' style='color:#999'>刚刚</small><div class='msg_content'>" + content + "</div></div></div>"); } }); //添加表情包1 for (var i = 1; i < 60; i++) { $(".emoji_1").append("<img src='img/f" + i + ".png' style='width:35px;height:35px' >"); } //添加表情包2 for (var i = 1; i < 61; i++) { $(".emoji_2").append("<img src='img/h" + i + ".png' style='width:35px;height:35px' >"); } $(".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("<img src='" + url + "' style='width:25px;height:25px' >"); $("#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>
login.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="../static/css/login.css" rel="stylesheet" type="text/css" media="all" > <!--<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="/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="登录"> <p style="color: red;">{{ get_flashed_messages() }}</p> <!-- 获取闪现的内容--> </form> <p>创建一个账号? <a href="/register/"> 立即注册!</a></p> </div> </div> <!-- copyright --> <div class="w3copyright-agile"> <p>© 2019 西部开源</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>
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="../static/css/login.css" rel="stylesheet" type="text/css" media="all" />#} <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>#} {# <label class="anim">#} {# <input type="checkbox" class="checkbox" required="">#} {# <span> 记住 ?</span> #} {# </label> #} {# </li>#} <li><a href="#">忘记密码 ?</a></li> </ul> <div class="clear"></div> </div> <input type="submit" value="注册"> <p style="color: red;">{{ get_flashed_messages() }}</p> <!-- 获取闪现信息--> </form> <p>已有账号? <a href="/login/"> 立即登录!</a></p> </div> </div> <!-- copyright --> <div class="w3copyright-agile"> <p>© 2019 西部开源</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>
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 %}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。