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+...+100
k = k + 1
s = s + k
print s
s = 0
for k in range(101): #该循环过程也是求1+2+3+...+100
s = 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:
# 同时处理两种异常,并将异常实例赋值给变量 e
pass
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 = name
self.age = age
self.gender = gender
self.email = email
self.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, EqualTo
app = 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'] = True
db = SQLAlchemy(app)
class User:
def __init__(self, name, age, gender, email, interests=None):
self.name = name
self.age = age
self.gender = gender
self.email = email
self.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.Model
id = 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.id
session['username'] = user.username
return 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了)
再注册一个重复的