文章目录
一、day02项目环境和结构搭建
1.1 项目根目录创建apps包
包内包含__init__.py文件
1.2 项目模板目录templates创建user子目录
user子应用中用到的页面 html 文件全部放到 templates\user 子目录中。
二、后端知识要点
2.1 蓝图Blueprint基础知识
2.1.1 为什么需要蓝图
随着flask程序越来越复杂,我们需要对程序进行模块化的处理,以利于大项目的开发。
2.1.2 什么是蓝图
- 蓝图(blueprint):是flask自带的一种开发模式,用于实现单个应用的视图、模板、静态文件的集合。
- 蓝图就是模块化处理的类,类似于Django中的app-子应用。
- 蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能。 在Flask中,使用蓝图可以帮助我们实现模块化应用的功能。
2.1.3 蓝图的属性
- 一个项目可以具有多个Blueprint。
- 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/”、“/sample”或者子域名。
- 在一个应用中,一个模块可以注册多次。
- Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的。
- 在一个应用初始化时,就应该要注册需要使用的Blueprint。
2.1.4 蓝图使用的步骤
2.1.4.1 创建一个蓝图的包,例如user,并在view.py文件中创建蓝图对象
from flask import Blueprint
user_bp = Blueprint('user', __name__)
2.1.4.2 view.py文件中创建当前蓝图使用的视图函数
- 使用蓝图后,反向解析url_for()需要用蓝图的名称点出路由别名。
- 使用蓝图后,模板渲染需要从templates文件夹开始指定html文件目录,可能包括多层目录。
@user_bp.route('/')
def user_center():
# print(url_for('user.register')) # 反向解析需要加上蓝图名称
return render_template('user/show.html', users=users)
2.1.4.3 apps包的初始化文件__init__.py中新建创建应用app的函数,并绑定蓝图
- 因为创建蓝图,改变了Flask默认目录结构,所以初始化app时需要重新指定模板和静态文件目录。
- 蓝图必须在初始化app时绑定到app上,才能发挥作用。
from flask import Flask
import settings
from apps.user.view import user_bp
def create_app():
app = Flask(__name__,
template_folder='../templates',
static_folder='../static',
)
app.config.from_object(settings)
# 将蓝图对象绑定到app
app.register_blueprint(user_bp)
print(app.url_map)
return app
2.1.4.4 项目根目录app.py调用函数创建app对象
- 调用函数创建app对象可以保持启动文件的干净、清爽。
from apps import create_app
app = create_app()
if __name__ == '__main__':
app.run(port=5002)
2.2 request对象获取前端提交的数据
2.2.1 接收前端两种方式提交的数据
- 蓝图路由中添加参数:methods=[‘GET’, ‘POST’]
- 反向解析默认的名称为函数名(如user_update);如果函数名较长,可以指定别名endpoint=‘update’。
- 每种方式都必须有返回值,否则会报错。
@user_bp.route('/update', methods=['GET', 'POST'], endpoint='update')
def user_update():
if request.method == 'POST':
# 获取post提交的数据
username = request.form.get('username')
return redirect('/')
if request.method == 'GET':
# 获取get提交的数据
username = request.args.get('username')
return render_template('user/update.html')
2.2.2 获取前端get方式提交的数据
- get(‘username’) 与前端的 name='username’对应
username = request.args.get('username')
2.2.3 获取前端post方式提交的数据
username = request.form.get('username')
2.3 model.py定义类
2.3.1 User类的定义
- 注意:类名首字母大写
class User:
def __init__(self, username, password, phone=None):
self.username = username
self.password = password
self.phone = phone
def __str__(self):
return self.username
2.3.2 User类的实例化
- 注意:类名首字母大写
from apps.user.model import User
user = User(username, password, phone)
三、前端知识要点
3.1 HTML页面文件的结构安排
- 基础母版文件base.html放到模板文件夹中:day02\templates
- user子应用的html文件放到模板文件夹的下级目录中:day02\templates\user
3.2 创建基础母版模板base.html
- html框架
- 预留标题block(title)
- 预留css样式block(mycss)
- 预留页面顶端block(head)
- 预留页面中部主体block(middel)
- 预留页面尾部block(foot)
- 预留javascript block(myjs)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %} 用户中心 {% endblock %}</title>
{% block mycss %}
{% endblock %}
</head>
<body>
<div id="head">
<ul>
<li><a href="">首页</a></li>
<li><a href="">秒杀</a></li>
<li><a href="">超市</a></li>
<li><a href="">图书</a></li>
<li><a href="">会员</a></li>
</ul>
{% block head%}{% endblock %}
</div>
<div id="middle">
{% block middle %}{% endblock %}
</div>
<div id="foot">
{% block foot%}{% endblock %}
</div>
{% block myjs %}{% endblock %}
</body>
</html>
3.3 模板的继承
3.3.1 继承基础母版base.html
- {% extends ‘base.html’ %} 一般放在子页面的第一行
- 项目所有html文件的起始查找目录,都是基于app初始化时的templates文件夹
{% extends 'base.html' %}
3.3.2 Block填坑
{% block title %}
用户展示
{% endblock %}
{% block middle %}
<span>当前用户人数时:{{ users|length }} 人</span>
<ul>
{% for user in users %}
<li>{{user.username}}-{{user.password}}-{{user.phone}}</li>
{% endfor %}
</ul>
<table border="solid 1" cellspacing="0" width="60%">
{% for user in users %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ user.username }}</td>
<td>{{ user.password }}</td>
<td>{{ user.phone }}</td>
<td><a href="javascript:;" onclick="update('{{ user.username }}')">修改</a>
<a href="javascript:;" onclick="del('{{ user.username }}')">删除</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% block myjs %}
<script type="text/javascript">
function del(username){
// console.log(username)
// location 地址栏对象
location.href = '/del?username=' + username
}
function update(username){
location.href = '/update?username=' + username
}
</script>
{% endblock %}
3.4 取消超链接href,自定义js
- href=“javascript:;” 为取消超链接
- οnclick=“del(‘{{ user.username }}’)” 为自定义js函数名称,特别注意:参数如果为字符串,需要双层引号。
- js函数参数接收和python相同,放到圆括号中。
- js中,location.href相当于重定向,可以拼接 路由 + ? + 变量名=value
<a href="javascript:;" onclick="del('{{ user.username }}')">删除</a>
<script type="text/javascript">
function del(username){
// console.log(username)
// location 地址栏对象
location.href = '/del?username=' + username
}
</script>
四、项目完整代码
4.1 项目目录结构
4.2 后端代码
4.2.1 配置文件settings.py
# 配置文件
ENV = 'development'
DEBUG = True
4.2.2 项目启动app.py
from apps import create_app
app = create_app()
if __name__ == '__main__':
app.run(port=5002)
4.2.3 user包初始化__init__.py
from flask import Flask
import settings
from apps.user.view import user_bp
def create_app():
app = Flask(__name__,
template_folder='../templates',
static_folder='../static',
)
app.config.from_object(settings)
# 将蓝图对象绑定到app
app.register_blueprint(user_bp)
print(app.url_map)
return app
4.2.4 user子应用model.py
class User:
def __init__(self, username, password, phone=None):
self.username = username
self.password = password
self.phone = phone
def __str__(self):
return self.username
4.2.5 user子应用视图view.py
from flask import Blueprint, request, render_template, redirect, url_for
from apps.user.model import User
user_bp = Blueprint('user', __name__)
# 列表保存用户对象
users = []
@user_bp.route('/')
def user_center():
# print(url_for('user.register')) # 反向解析需要加上蓝图名称
return render_template('user/show.html', users=users)
@user_bp.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
# 获取post提交的数据
username = request.form.get('username')
password = request.form.get('password')
repassword = request.form.get('repassword')
phone = request.form.get('phone')
if password == repassword:
# 保证用户名唯一
for user in users:
if user.username == username:
msg = '用户名已存在!'
print(msg)
return render_template('user/register.html', msg=msg)
#4.4蓝图1:04:35
# 创建user对象
user = User(username, password, phone)
# 添加到用户列表
users.append(user)
# print(users)
return redirect('/')
else:
return render_template('user/register.html', msg='密码不一致!')
return render_template('user/register.html')
@user_bp.route('/login', methods=['GET', 'POST'])
def login():
return '用户登录'
@user_bp.route('/logout', methods=['GET', 'POST'])
def logout():
return '用户退出'
@user_bp.route('/del')
def del_user():
# 获取传递过来的username
username = request.args.get('username')
# 根据username找到列表中的对象
for user in users:
if user.username == username:
users.remove(user)
return redirect('/')
else:
return '删除失败'
@user_bp.route('/update', methods=['GET', 'POST'], endpoint='update')
def user_update():
if request.method == 'POST':
# post请求
realname = request.form.get('realname')
username = request.form.get('username')
password = request.form.get('password')
phone = request.form.get('phone')
# 判断用户名是否重复
for user in users:
if user.username == username:
return render_template('user/update.html', msg='用户名重复!')
else:
for user in users:
if user.username == realname:
user.username = username
user.phone = phone
return redirect('/')
else:
# get请求
username = request.args.get('username')
for user in users:
# 匹配用户
if user.username == username:
return render_template('user/update.html', user=user)
4.3 前端代码
4.3.1 项目基础母版base.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %} 用户中心 {% endblock %}</title>
<style type="text/css">
#head {
height: 3.125rem;
background-color: bisque;
}
#head ul li {
float: left;
width: 6.25rem;
text-align: center;
font-size: 1.125rem;
height: 3.125rem;
line-height: 3.125rem;
}
#middle {
height: 56.25rem;
background-color: azure;
}
#foot {
height: 3.125rem;
line-height: 3.125rem;
background-color: darkseagreen;
}
</style>
{% block mycss %}
{% endblock %}
</head>
<body>
<div id="head">
<ul>
<li><a href="">首页</a></li>
<li><a href="">秒杀</a></li>
<li><a href="">超市</a></li>
<li><a href="">图书</a></li>
<li><a href="">会员</a></li>
</ul>
</div>
<div id="middle">
{% block middle %}{% endblock %}
</div>
<div id="foot">
</div>
{% block myjs %}
{% endblock %}
</body>
</html>
4.3.2 user子应用注册页面register.html
{% extends 'base.html' %}
{% block title %}
用户注册
{% endblock %}
{% block middle %}
<p style="color: red"> {{ msg }}</p>
<form action="{{ url_for('user.register') }}" method="post">
<p><input type="text" name="username" placeholder="用户名"></p>
<p><input type="password" name="password" placeholder="密码"></p>
<p><input type="password" name="repassword" placeholder="确认密码"></p>
<p><input type="number" name="phone" placeholder="手机号码"></p>
<p><input type="submit" value="用户注册"></p>
</form>
{% endblock %}
4.3.3 user子应用用户展示页面
{% extends 'base.html' %}
{% block title %}
用户展示
{% endblock %}
{% block middle %}
<span>当前用户人数时:{{ users|length }} 人</span>
<ul>
{% for user in users %}
<li>{{user.username}}-{{user.password}}-{{user.phone}}</li>
{% endfor %}
</ul>
<table border="solid 1" cellspacing="0" width="60%">
{% for user in users %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ user.username }}</td>
<td>{{ user.password }}</td>
<td>{{ user.phone }}</td>
<td><a href="javascript:;" onclick="update('{{ user.username }}')">修改</a>
<a href="javascript:;" onclick="del('{{ user.username }}')">删除</a></td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% block myjs %}
<script type="text/javascript">
function del(username){
// console.log(username)
// location 地址栏对象
location.href = '/del?username=' + username
}
function update(username){
location.href = '/update?username=' + username
}
</script>
{% endblock %}
4.3.4 user子应用用户更新页面update.html
{% extends 'base.html' %}
{% block title %}
用户信息修改
{% endblock %}
{% block middle %}
<h1>用户信息更新</h1>
<p style="color: red"> {{ msg }}</p>
<form action="{{ url_for('user.update') }}" method="post">
<p><input type="hidden" name="realname" id="" value="{{ user.username }}" /></p>
<p><input type="text" name="username" placeholder="用户名" value="{{ user.username }}"></p>
<p><input type="text" name="password" placeholder="密码" value="{{ user.password }}" disable></p>
<p><input type="number" name="phone" placeholder="手机号码" value="{{ user.phone }}"></p>
<p><input type="submit" value="用户更新"></p>
</form>
{% endblock %}