赞
踩
前言
这几天学习了flask的框架,这里总结一些学习的历程flask是轻量级的web框架。 浏览器作为client发出HTTP请求,而web服务器负责处理逻辑,而flask帮助我们完成了安全性和数据流的控制,让我们只用关注于业务逻辑本身,避免重复造轮子
需要注意的点:
(1) 此flask程序运行在flask提供的简易服务器上,flask包括路由模块与模板引擎两个部分。所以需要提供服务器地址,@app.route(’/’)就提供了地址,默认是根目录,且默认是支持GET,再后面的WTF表单使用上我们还能用到POST(其实就是类似于输入账号密码)然后得到反馈。
(2)路由模块之后紧接着就是模板引擎,模板引擎可以返回一个字符串或者是一个html文件,html文件需要render_template模块的支持。而html文件中为了在页面中显示后端的传来的数据,需要使用变量代码块以及控制代码块,通常有两个花括号,参考下方的html代码
代码如下:
#导入flask扩展 from flask import Flask,render_template from flask_sqlalchemy import SQLAlchemy #创建flask应用程序实例,需要传入__name__,为了确定资源所在路径 app = Flask(__name__) #定义路由以及视图函数,通过装饰器,根路由 #路由默认只支持GET,如果需要增加,需要自行指定 @app.route('/') def index(): # return '<h1>Hello World!</h1>' #传入网址,模板引擎的使用 #变量代码块的使用 url_str ='www.xidian.com' my_list=[1,2,3,4,5] my_dict={ 'name':'czz' , 'url':'www.xidian.com' } return render_template('index.html', url_str=url_str, my_list=my_list, my_dict=my_dict) # <>定义路由参数,<>内需要起个名字 @app.route('/orders/<int:order_id>') def get_order_id(order_id): #需要在视图函数内填入参数名,后面代码才能使用 print(type(order_id)) return 'order_id %s'%order_id if __name__ == '__main__': #将Flask程序运行在一个简易服务器上(flask提供) app.run(debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 这是模板<br> 这是首页<br> <!--下面是一个变量代码块的使用--> {{my_list}}<br> {{my_list[2]}}<br> {{my_dict}}<br> {{my_dict.name}}<br> {{url_str}}<br> <hr> <!--控制代码块,用花括号,基本语法仍然相同--> {% for num in my_list %} {% if num>3 %} {{num}}<br> {% endif %} {% endfor %} <hr> <!--过滤器--> {{ url_str | upper}}<br> {{ url_str | reverse}}<br> <!--过滤器链式调用--> {{ url_str | reverse | upper}}<br> </body> </html>
结果显示:
问题分析:
(1). WTF为我们封装了登录的相关的逻辑,我们利用wtf来实现表单类,继承自FlaskForm
(2) .我们需要有登录账号,密码,以及密码确认。因此需要username,以及password1,password2,submit。validators是为了表单的验证,如果有表单数据有误会在页面中显示参数错误。
(3).我们为了需要完成与前端的页面的交互,必须利用模板引擎来定义表单类并获取请求的参数
(4)注意利用wtf实现表单类的时候需要设置secret_key进行加密,并在前端代码中加入{{ form.csrf_token() }}
代码如下:
from flask import Flask,render_template,request,flash from flask_wtf import FlaskForm from wtforms import StringField,PasswordField,SubmitField from wtforms.validators import DataRequired,EqualTo app=Flask(__name__) app.secret_key='xdu' #目的:实现简单的登录逻辑处理 #路由需要有get和post两种请求方式,需要判断请求方式 #获取请求参数 #判断参数是否填写以及密码是否相同 #如果判断没有问题则返回一个success ''' 给模板传递消息 flash 需要对内容加密,需要设置secret_key,做加密消息的混淆 模板中需要遍历消息 ''' ''' 使用wtf实现表单类 ''' class LoginForm(FlaskForm): username=StringField('用户名',validators=[DataRequired()]) password=PasswordField('密码',validators=[DataRequired(),EqualTo('password','密码不一致')]) password2 = PasswordField('确认密码') submit=SubmitField('提交') @app.route('/form',methods=['GET','POST']) def login(): login_form=LoginForm() # 1.request 是一个请求对象-->获取请求方式,数据. if request.method == 'POST': # 2.获取请求参数 username = request.form.get('username') password = request.form.get('password') password2 = request.form.get('password2') # 3.wtf验证逻辑的实现 if login_form.validate_on_submit(): print(username , password) return 'success' else: flash('参数有误') return render_template('index.html',form=login_form) @app.route('/',methods=['GET','POST']) def index(): #1.request 是一个请求对象-->获取请求方式,数据. if request.method =='POST': #2.获取请求参数 username =request.form.get('username') password =request.form.get('password') password2 = request.form.get('password2') # 3.判断参数是否相同 密码是否相同 if not all([username,password,password2]): # print('参数不完整') flash('参数不完整') elif password!=password2: # print('密码不一致') flash('密码不一致') else: return 'success' return render_template('index.html') if __name__ == '__main__': app.run(debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> <label>用户名:</label><input type="text" name="username"><br> <label>密码:</label><input type="password" name="password"><br> <label>确认密码:</label><input type="password" name="password2"><br> <input type="submit" value="提交"><br> {% for message in get_flashed_messages() %} {{message}} {% endfor %} </form> <hr> <form method="post"> {{ form.csrf_token() }} {{form.username.label}}{{form.username}}<br> {{form.password.label}}{{form.password}}<br> {{form.password2.label}}{{form.password2}}<br> {{form.submit}} </form> </body> </html>
这里进行配置数据库,并建立两张表,一张是角色,一张是用户。
User希望有role属性,这个属性的定义需要在另一个模型中定义 使得user可以直接查到role,这样做的目的是为了方便查找,两个模型之间实现了关联
# coding=<encoding name> : # coding=utf-8 from flask import Flask, render_template, redirect, url_for, flash, request from flask_sqlalchemy import SQLAlchemy from flask_wtf.csrf import CSRFProtect import pymysql app = Flask(__name__) #设置数据库配置信息 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@127.0.0.1:3306/flask_use_sql' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #压制警告信息 db=SQLAlchemy(app) app.config['SECRET_KEY'] = "jfkdjfkdkjf" ''' 需求:两张表 角色(管理员/普通用户) 用户(角色ID) ''' #数据库模型,需要继承db.Modelf class Role(db.Model): #定义表名 __tablename__='roles' #定义字段 db.Column表示是一个字段 id=db.Column(db.Integer,primary_key=True) name = db.Column(db.String(64), unique=True) #在一的一方,写关联 #表示和User模型发生关联,增加了一个users属性 user=db.relationship('User', backref='role') # 重写__repr__方法,方便查看对象输出内容 def __repr__(self): return 'Role:%s'% self.name class User(db.Model): __tablename__='users' id=db.Column(db.Integer,primary_key=True) name = db.Column(db.String(16), unique=True) email = db.Column(db.String(64), unique=True) password = db.Column(db.String(64)) # db.ForeignKey('roles.id') 表示是外键,需要用 表名.id形式表示 role_id=db.Column(db.Integer,db.ForeignKey('roles.id')) #User希望有role属性,这个属性的定义需要在另一个模型中定义 使得user可以直接查到role 反之亦然 def __repr__(self): return '<User:%s %s %s %s >' % self.name,self.id,self.email,self.password @app.route('/') def index(): return 'hello flask' if __name__ == '__main__': # #删除表 db.drop_all() # #创建表 db.create_all() role=Role(name='admin') db.session.add(role) db.session.commit() user1= User(name='czz',role_id=role.id) user2 = User(name='lisi', role_id=role.id) db.session.add_all([user1,user2]) db.session.commit() # user.name='czz tcl' db.session.commit() # db.session.delete(user) # db.session.commit() # print(user2.role) app.run(debug=True)
# -*- coding:utf-8 -*- from flask import Flask, render_template, redirect, url_for, flash, request from flask_sqlalchemy import SQLAlchemy from flask_wtf import FlaskForm from wtforms.validators import DataRequired from wtforms import StringField,SubmitField from flask_wtf.csrf import CSRFProtect #import sys #reload(sys) #sys.setdefaultencoding("utf-8") app=Flask(__name__) #配置数据库 数据库地址 关闭自动跟踪修改 app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@127.0.0.1:3306/flask_project_demo' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False #压制警告信息 app.config['SECRET_KEY'] = "123456" # #开启csrf保护 # CSRFProtect(app) #创建数据库对象 db=SQLAlchemy(app) ''' 1.配置数据库 a.导入SQLAlchemy扩展 b.创建db对象,并配置参数 c.创建终端数据库 2.添加书和作者的模型 a.模型继承db.Model b.__tablename__表名 c.db.Column:字段 d.db.relationship:关系引用 3.添加数据 4.使用模板显示数据库查询的数据 a.查询所有作者信息,让信息传给模板 b.模板中按照格式,依次for循环作者和书籍即可 5.使用wtf显示表单 a.自定义表单类 b.模板中显示 c.secret_key/编码/csrf_token 6.实现相关的增删逻辑处理 a.增加数据 b.删除书籍 -->网页中删除--点击需要发送书籍的ID给删除书籍的路由-->路由需要接收参数 url_for的使用 /for else 的使用/ redirect的使用 c.删除 ''' #定义书和作者模型 #作者模型 class Author(db.Model): # 表名 __tablename__ = 'authors' # 字段 id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(64), unique=True) # 关系引用 # books自己使用,author是给book模型使用的 books = db.relationship('Book',backref='author') def __repr__(self): return 'Author:%s' % self.name class Book(db.Model): __tablename__='books' id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(64), unique=True) author_id=db.Column(db.Integer,db.ForeignKey('authors.id')) def __repr__(self): return 'Book:%s' % (self.name,self.author_id) #自定义表单类: class AuthorForm(FlaskForm): author =StringField('作者', validators=[DataRequired()]) book = StringField('书籍', validators=[DataRequired()]) submit=SubmitField('提交') #删除作者 @app.route('/delete_author/<author_id>') def delete_author(author_id): # 查询数据库,是否有改ID的作者,如果有就删除(先删除书后删除作者) # 1.查询数据库 author =Author.query.get(author_id) # 2.如果有就删除 if author: try: # 查询后直接删除 Book.query.filter_by(author_id=author_id).delete # 删除作者 db.session.delete(author) db.session.commit() except Exception as e: print(e) flash('删除作者错误') db.session.rollback() else: # 没有提示错误 flash('作者找不到') return redirect(url_for('index')) # 删除书籍 -->网页中删除--> 点击需要发送书籍的ID给删除书籍的路由-->路由需要接收参数 @app.route('/delete_book/<book_id>') def delete_book(book_id): # 1.查询数据库是否有该id的书,如果有就删除,没有就提示错误 book=Book.query.get(book_id) # 2.如果有就删除 if book: try: db.session.delete(book) db.session.commit() except Exception as e: print(e) flash('删除书籍错误') db.session.rollback() else: # 3.没有提示错误 flash('书籍找不到') # 如何返回当前网址——>重定向 # redirect:重定向,需要传入网址/路由地址 # url_for:需要传入视图函数名,返回该视图函数对应的路由地址 return redirect(url_for('index'))# 结果和redirect('/')一样 @app.route('/',methods=['GET','POST']) def index(): #创建自定义的表单类 author_form=AuthorForm() ''' 验证逻辑: 1.调用wtf的函数实现验证 2.验证通过获取数据 3.判断作者是否存在 4.如果作者存在,判断书籍是否存在,如果没重复就添加数据,反之提示错误 5。作者不存在,添加作者和书籍 6.验证不通过就提示错误 ''' #1.调用WTF的函数实现验证 if author_form.validate_on_submit(): #2.通过验证获取数据 author_name=author_form.author.data book_name = author_form.book.data #3.判断作者是否存在 author=Author.query.filter_by(name=author_name).first() #4.如果作者存在 if (author) : # 判断书籍是否存在 book=Book.query.filter_by(name=book_name).first() if (book): flash('存在同名书籍') #没有重复的书籍就添加数据 else: try: new_book=Book(name=book_name,author_id=author.id) db.session.add(new_book) db.session.commit() except Exception as e: print(e) flash('添加书籍失败') db.session.rollback() pass else: #5.作者不存在,添加作者和书籍 try: new_author = Author(name=author_name) db.session.add(new_author) db.session.commit() new_book = Book(name=book_name, author_id=new_author.id) db.session.add(new_book) db.session.commit() except Exception as e: print(e) flash('添加作者和书籍失败') db.session.rollback() pass pass else: if request.method == 'POST': flash('参数不全') # 查询所有的作者信息,让信息查给模板 authors = Author.query.all() return render_template('library.html', authors=authors, form=author_form) if __name__ =='__main__': # 为了演示方便,先删除所有表,再创建 db.drop_all() db.create_all() # 添加测试数据库 # 生成数据 au1 = Author(name='隔壁老王') au2 = Author(name='老李') au3 = Author(name='二营长') # 把数据提交给用户会话 db.session.add_all([au1, au2, au3]) # 提交会话 db.session.commit() bk1 = Book(name='learn', author_id=au1.id) bk2 = Book(name='science', author_id=au1.id) bk3 = Book(name='art', author_id=au2.id) bk4 = Book(name='beautiful', author_id=au3.id) bk5 = Book(name='handsome', author_id=au3.id) # 把数据提交给用户会话 db.session.add_all([bk1, bk2, bk3, bk4, bk5]) # 提交会话 db.session.commit() app.run(debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> {{ form.csrf_token()}} {{ form.author.label()}}{{form.author}} {{ form.book.label()}}{{form.book}} {{ form.submit }} <!-- 显示消息闪现的内容--> {% for message in get_flashed_messages() %} {{message}} {% endfor %} </form> <hr> <ul> <!-- #先遍历作者,然后在作者里遍历书籍--> {% for author in authors %} <li>{{ author.name }}<a href="{{url_for('delete_author',author_id=author.id)}}">删除</a> </li></li> <ul> {% for book in author.books %} <li>{{ book.name }}<a href="{{url_for('delete_book',book_id=book.id)}}">删除</a> </li> {% else %} <li>无</li> {% endfor %} </ul> {% endfor %} </ul> </body> </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。