python基础
服务端开发编程
第一个是赋值运算,第二是乘法,最后是一个是幂(即a2)
a = 2
a * 2
a ** 2
Python支持多重赋值:
a, b, c = 2, 3, 4
这句命令相当于:
a = 2
b = 3
c = 4
Python支持对字符串的灵活操作
s = ‘I like python’
s + ’ very much’ #将 s 与’ very much’拼接,得到’I like python very much’
s.split(’ ') #将 s 以空格分割,得到列表[‘I’, ‘like’, ‘python’]
输入 input() 函数
# 获取用户输入
user_input = input("输入你的姓名: ")
# 打印用户输入的内容
print("Hello, " + user_input + "!")# 获取用户输入并转换为整数
age = int(input("几岁啦? "))
# 使用输入的整数值
print("我明年就要 " + str(age + 1) + " 岁啦!")
输出print() 函数
# 打印简单的字符串print("Hello, World!")
# 打印变量
name = "Alice"
print("Hello, " + name + "!")
# 使用格式化字符串
print("Hello, {}!".format(name))
# 使用 f-strings (Python 3.6+)print(f"Hello, {name}!")
# 打印多个参数
print("Hello", name, "Welcome to the Python world!")
# 打印时不换行
print("First line,", end=" ")print("Second line.")
程序基本结构(选择)
if 条件1:语句2
elif 条件3:语句4
else:语句5
程序基本结构(循环)
s,k = 0,0
w h i l e k < 1 0 1 : # 该 循 环 过 程 就 是 求
1+2+3+...+100k = k + 1s = s + k
print s
s = 0
for k in range(101): #该循环过程也是求1+2+3+...+100s = s + k
print s
程序基本结构(in语句)
s = 0
if s in range(4):print(u's在0, 1, 2, 3中')
if s not in range(1, 4, 1):print(u's不在1, 2, 3中')
Python用def来自定义函数:
def add2(x):return x+2
print(add2(1) )#输出结果为3
Python的函数返回值可以是各种形式,比如返回列表,甚至返回多个值:
def add2(x = 0, y = 0): #定义函数,同时定义参数的默认值return [x+2, y+2] #返回值是一个列表
def add3(x, y):return x+3, y+3 #双重返回
a, b = add3(1,2) #此时a=4,b=5
Python支持用lambda对简单的功能定义“行内函数”
f = lambda x : x + 2 #定义函数f(x)=x+2
g = lambda x, y: x + y #定义函数g(x,y)=x+y
在Python 3中,**kwargs 是一个非常有用的功能,它允许你向函数传递任意数量的关键字参数。
这些参数在函数内部作为一个字典来处理,即能够接受任意数量的参数,而不必事先知道这些参数的名称或数量。
def print_kwargs(**kwargs):for key, value in kwargs.items():print(f"{key} = {value}")print_kwargs(name='Alice', age=25, city='New York')
**kwargs 与固定参数结合使用
def print_info(name, **kwargs):print(f"Name: {name}")for key, value in kwargs.items():print(f"{key} = {value}")print_info('Bob', job='Engineer', country='USA')
Python 有四个内建的数据结构,统称为容器(container),可以是数字、字符甚至是列表,或者是它们之间几种的组合:【注意】容器里边的元素类型可以不相同。
- List(列表)
- Tuple(元组)
- Dictionary(字典)
- Set(集合)
异常处理用try和except关键字来实现。当程序执行try块中的代码时,如果发生了异常,程序的执行将立即跳转到except块。except块允许程序对异常做出响应,而不是让程序崩溃。
while True:try:age = int(input("几岁啦? "))break # 如果转换成功,退出循环except ValueError:print("转换出错.")
捕捉多种异常
try:# 可能引发多种异常的代码pass
except TypeError:# 处理TypeError异常pass
except ValueError:# 处理ValueError异常pass
except (ExceptionType1, ExceptionType2) as e:# 同时处理两种异常,并将异常实例赋值给变量 epass
except Exception as e:# 捕获所有非系统退出类的异常pass
Jinja2模板
Jinja2模板主要内容
- 渲染模板、变量
- 控制语句
- 模板结构
- 加载静态文件
Jinja2模板介绍
- Jinja2 是一个现代的、设计者友好的、仿照 Django 模板的Python 模板语言。
- 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全
- Jinja2 需要至少 Python 2.4 版本来运行
- pip install Jinja2 (安装Jinja2)
两种分隔符
- 分隔符{% … %}
- 用于执行诸如 for 循环或赋值的语句
- 分隔符 {{ … }}
- 表达式的结果打印到模板上
注释
- 使用 {# … #} 注释语法
表单
Flask-WTF创建表单的步骤
- 定义表单类。决定表单中的一组字段(Field),每个Field都有对象表示,可附属一个或多个验证函数,验证函数用于验证用户提交的数据是否有效。
- 定义模板页面。定义HTML表单。
- 定义视图函数。视图函数主要是渲染表单,接收用户在表单中填写的数据。
- 重定向页面。作为post请求的响应(Post–>重定向–>Get模式)。
WTForms支持的HTMLField类
WTForms常用验证器
EX1:“hello,xx”案例改成表单输入xx
定义表单类
定义模板页面
Bootstrap引入
- 安装flask-bootstrap
- 在app.py中引入Bootstrap
- 在模板页中继承bootstrap的母板,并修改母板中定义的content模块
用户会话(session)
若要保存EX1中用户输入的名字,可考虑使用用户会话,即session[‘xx’],其中“xx”为自定义名称
闪现消息(flash函数)
需要让用户知道程序的状态变化,Flask内置了设置提示信息,比并传递到页面显示
数据库连接访问
使用Flask-SQLAlchemy管理数据库
在Flask-SQLAlchemy中,数据库使用URL指定
配置数据库
定义模型
模型表示应用使用的持久化实体,在ORM中,表现为一个Python类,类中的属性对应数据库表中的列
最常用的SQLAlchemy列类型
最常用的SQLAlchemy列的属性选项
【注意】每个模型都定义主键,一般命名为id
关系
关系型数据库使用关系把不同表中的行联系起来,例如,5.1案例中的关系图表示角色和用户之间存在一对多关系,即1个角色可能有多个用户。
常用的SQLAlchemy关系选项
梳理下关系类型
- 一对多关系(多对一关系)
- 一对一关系
- db.relationship()中的uselist选项设置为False
- 多对多关系
- 需要第3张关系表(关联表或联结表),后面的课再讨论
数据库操作
- 插入行
- 修改行
- 删除行
- 查询行
常用的SQLAlchemy查询过滤器
常用的SQLAlchemy查询执行方法
前后端分离开发
Restful API
客户端异步请求补充
跨域请求
图表应用
文件上传
Flask练习
练习1-1
代码段:
@app.route('/')
def index():name = request.args.get('name', '陌生人')return render_template('index.html', name=name)
<!DOCTYPE html>
<html>
<head><title>Greeting</title>
</head>
<body><h1>你好,{{ name }}</h1>
</body>
</html>
实现效果
练习1-2
代码片段
class User:def __init__(self, name, age, gender, email, interests=None):self.name = nameself.age = ageself.gender = genderself.email = emailself.interests = interests if interests else []@app.route('/user')
def user_view():# 自定义用户属性值user_info = {'name': 'ZhangSan','age': 25,'gender': 'Female','email': 'alice@example.com','interests': ['reading', 'traveling', 'coding']}user = User(**user_info)return render_template('user.html', user=user)
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>User Information</title><!-- Bootstrap CSS --><link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body><div class="container mt-5"><div class="row"><div class="col-md-4"><div class="card" style="width: 18rem;"><img class="card-img-top" src="{{ url_for('static', filename='/images/zhangsan.jpg') }}" alt="User image"><div class="card-body"><h5 class="card-title">{{ user.name }}</h5><ul class="list-unstyled"><li><strong>年龄:</strong> {{ user.age }}</li><li><strong>性别:</strong> {{ user.gender }}</li><li><strong>EMail:</strong> {{ user.email }}</li><li><strong>兴趣:</strong> {{ ', '.join(user.interests) }}</li></ul><a href="#" class="btn btn-primary">联系我们</a></div></div></div><div class="col-md-4"><div class="card" style="width: 18rem;"><img class="card-img-top" src="{{ url_for('static', filename='/images/zhangsan.jpg') }}" alt="User image"><div class="card-body"><h5 class="card-title">{{ user.name }}</h5><ul class="list-unstyled"><li><strong>年龄:</strong> {{ user.age }}</li><li><strong>性别:</strong> {{ user.gender }}</li><li><strong>EMail:</strong> {{ user.email }}</li><li><strong>兴趣:</strong> {{ ', '.join(user.interests) }}</li></ul><a href="#" class="btn btn-primary">联系我们</a></div></div></div><div class="col-md-4"><div class="card" style="width: 18rem;"><img class="card-img-top" src="{{ url_for('static', filename='/images/zhangsan.jpg') }}" alt="User image"><div class="card-body"><h5 class="card-title">{{ user.name }}</h5><ul class="list-unstyled"><li><strong>年龄:</strong> {{ user.age }}</li><li><strong>性别:</strong> {{ user.gender }}</li><li><strong>EMail:</strong> {{ user.email }}</li><li><strong>兴趣:</strong> {{ ', '.join(user.interests) }}</li></ul><a href="#" class="btn btn-primary">联系我们</a></div></div></div></div></div><!-- Bootstrap JS and dependencies --><script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
实现效果
练习1-3
代码实现
base.html
html复制代码<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{% block title %}Coffee House{% endblock %}</title><link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet"><style>.navbar-dark .navbar-brand {color: #fff;}.navbar-dark .nav-link {color: #fff;}</style>
</head>
<body>{% include '_top.html' %}<div class="container mt-5">{% block content %}{% endblock %}</div>{% include '_footer.html' %}<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
_top.html
html复制代码<nav class="navbar navbar-expand-lg navbar-dark bg-dark"><a class="navbar-brand" href="#">随缘咖啡屋</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav ml-auto"><li class="nav-item"><a class="nav-link" href="#">Login</a></li></ul></div>
</nav>
_footer.html
html复制代码<footer class="footer mt-auto py-3 bg-light"><div class="container text-center"><span class="text-muted">copyright© 2024 zjyivi</span></div>
</footer>
user_b.html
{% extends 'base.html' %}{% block title %}王婆说媒{% endblock %}{% block content %}
<div class="text-center my-5"><h1>hi, {{ name }}! 欢迎光临王婆说媒</h1><p>祝你不在家里,就在去相亲的路上~</p>
</div>
<div class="row">{% for i in range(3) %}<div class="col-md-4 mb-4"><div class="card"><img class="card-img-top" src="{{ url_for('static', filename='/images/zhangsan.jpg') }}" alt="User image"><div class="card-body text-center"><h5 class="card-title">{{ user.name }}</h5><ul class="list-unstyled"><li><strong>年龄:</strong> {{ user.age }}</li><li><strong>性别:</strong> {{ user.gender }}</li><li><strong>EMail:</strong> {{ user.email }}</li><li><strong>兴趣:</strong> {{ ', '.join(user.interests) }}</li></ul><a href="#" class="btn btn-primary">联系我们</a></div></div></div>{% endfor %}
</div>
{% endblock %}
app.py
新增
@app.route('/user_b')
def user_view_b():user_info = {'name': '张三','age': 18,'gender': '女','email': 'zhangsan@hznu.edu.cn','interests': ['游泳', '跑步', '爬山', '阅读']}user = User(**user_info)name = request.args.get('name', '陌生人')return render_template('user_b.html', user=user, name=name)
实现效果:
练习2
看看表先
一开始连不上
debug是路径问题,这里必须绝对路径
代码实现:
app.py
from flask import Flask, render_template, request, redirect, url_for, session, flash
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Length, EqualToapp = Flask(__name__)
app.config['SECRET_KEY'] = 'Jay17_2004_06_26'
# 绝对路径
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(basedir,'data.sqlite')
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Truedb = SQLAlchemy(app)class User:def __init__(self, name, age, gender, email, interests=None):self.name = nameself.age = ageself.gender = genderself.email = emailself.interests = interests if interests else []@app.route('/')
def index():name = request.args.get('name', '陌生人')return render_template('index.html', name=name)@app.route('/user')
def user_view():# 自定义用户属性值user_info = {'name': 'ZhangSan','age': 25,'gender': 'Female','email': 'alice@example.com','interests': ['reading', 'traveling', 'coding']}user = User(**user_info)return render_template('user.html', user=user)@app.route('/user_b')
def user_view_b():user_info = {'name': '张三','age': 18,'gender': '女','email': 'zhangsan@hznu.edu.cn','interests': ['游泳', '跑步', '爬山', '阅读']}user = User(**user_info)name = request.args.get('name', '陌生人')return render_template('user_b.html', user=user, name=name)class Users(db.Model): # 确保 Users 继承自 db.Modelid = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(150), unique=True, nullable=False)password = db.Column(db.String(150), nullable=False)class LoginForm(FlaskForm):username = StringField('用户名', validators=[DataRequired(), Length(min=2, max=150)])password = PasswordField('密码', validators=[DataRequired(), Length(min=6, max=150)])submit = SubmitField('登录')class RegistrationForm(FlaskForm):username = StringField('用户名', validators=[DataRequired(), Length(min=2, max=150)])password = PasswordField('密码', validators=[DataRequired(), Length(min=6, max=150)])confirm_password = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('注册')@app.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()if form.validate_on_submit():user = Users.query.filter_by(username=form.username.data).first()if user and user.password == form.password.data:session['user_id'] = user.idsession['username'] = user.usernamereturn redirect(url_for('profile'))else:flash('登录信息有误!', 'danger')return render_template('login.html', form=form)@app.route('/register', methods=['GET', 'POST'])
def register():form = RegistrationForm()if form.validate_on_submit():if len(form.username.data) < 2:flash('用户名必须至少2位', 'danger')elif len(form.password.data) < 6:flash('密码必须至少6位', 'danger')else:user = Users.query.filter_by(username=form.username.data).first()if user:flash('用户名已注册', 'danger')else:new_user = Users(username=form.username.data, password=form.password.data)db.session.add(new_user)db.session.commit()return redirect(url_for('login'))return render_template('register.html', form=form)@app.route('/profile')
def profile():if 'user_id' not in session:return redirect(url_for('login'))return render_template('profile.html', username=session.get('username'))@app.route('/logout')
def logout():session.clear()return redirect(url_for('login'))if __name__ == '__main__':with app.app_context():db.create_all() # 创建所有数据库表app.run(debug=False)
_top.html
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"><a class="navbar-brand" href="#">王婆说媒</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav ml-auto"><li class="nav-item"><a class="nav-link" href="/login">Login</a></li></ul></div>
</nav>
base_login.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>{% block title %}My Site{% endblock %}</title><link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>{% include '_top_login.html' %}<div class="container mt-5">{% with messages = get_flashed_messages(with_categories=true) %}{% if messages %}{% for category, message in messages %}<div class="alert alert-{{ category }} alert-dismissible fade show" role="alert">{{ message }}<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button></div>{% endfor %}{% endif %}{% endwith %}{% block content %}{% endblock %}</div>{% include '_footer.html' %}<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script><script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
_top_login.html
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"><a class="navbar-brand" href="/">Web服务端案例</a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><div class="collapse navbar-collapse" id="navbarNav"><ul class="navbar-nav ml-auto">{% if 'username' in session %}<li class="nav-item"><a class="nav-link" href="{{ url_for('profile') }}">{{ session.username }}</a></li><li class="nav-item"><a class="nav-link" href="{{ url_for('logout') }}">退出登录</a></li>{% else %}<li class="nav-item"><a class="nav-link" href="{{ url_for('login') }}">登录</a></li><li class="nav-item"><a class="nav-link" href="{{ url_for('register') }}">注册</a></li>{% endif %}</ul></div>
</nav>
_footer.html
<footer class="footer mt-auto py-3 bg-light"><div class="container text-center"><span class="text-muted">copyright© 2024 Jay17</span></div>
</footer>
login.html
{% extends 'base_login.html' %}{% block title %}用户登录{% endblock %}{% block content %}
<h2 class="text-center">用户登录</h2>
<form method="POST" action="">{{ form.hidden_tag() }}<div class="form-group">{{ form.username.label() }}{{ form.username(class="form-control") }}</div><div class="form-group">{{ form.password.label() }}{{ form.password(class="form-control") }}</div><div class="form-group">{{ form.submit(class="btn btn-primary") }}</div>
</form>
{% endblock %}
register.html
{% extends 'base_login.html' %}{% block title %}用户注册{% endblock %}{% block content %}
<h2 class="text-center">用户注册</h2>
<form method="POST" action="">{{ form.hidden_tag() }}<div class="form-group">{{ form.username.label() }}{{ form.username(class="form-control") }}</div><div class="form-group">{{ form.password.label() }}{{ form.password(class="form-control") }}</div><div class="form-group">{{ form.confirm_password.label() }}{{ form.confirm_password(class="form-control") }}</div><div class="form-group">{{ form.submit(class="btn btn-primary") }}</div>
</form>
{% endblock %}
profile.html
{% extends 'base_login.html' %}{% block title %}用户中心{% endblock %}{% block content %}
<h2 class="text-center">hello,{{ username }}!</h2>
{% endblock %}
实现效果:
/user_b
路由
点击登录跳转至/login
路由
登录有误一下先
然后再成功一下
点击退出登录
先注册一个太短的(应该是模板的原因,这边前端就被拦截了,所以就轮不到后端flash了)
再注册一个重复的