项目 filter 编写 (作者/出版社/价格)
- view_models/book.py
- 通过filter去过滤 判断以下某一项存在及保存,通过“/"去连接
- @property 可以通过属性去调用 不用写() book.intro
@property //可以通过属性去调用 不用写() book.intro
def intro(self):
intros = filter(lambda x: True if x else False
[self.author,self.publisher,self.price])
return "/".join(intros)
编写 图书查看详情接口
@web.route('/book/<isbn>/detail')
def book_detail(isbn):
yushubook = YuShuBook()
yushubook.search_by_isbn(isbn)
book = BookViewModel(yushubook.first)
return render_template('book_detail.html',book=book,wishes=[],gifts=[])
- yushu_book.py
@property
def first(self):
return self.books[0] if self.total >=1 else None
模型与模型
- gift.py
- relationship (关联数据库)
- ForeignKey (创建关联数据库的表字段)
from app.models.base import db, Base
from sqlalchemy import Column,Integer,String,Boolean,ForeignKey
from sqlalchemy.orm import relationship
class Gift(Base):
id = Column(Integer,primary_key=True)
user = relationship('User')#关联的数据库
uid = Column(Integer,ForeignKey('user.id')) #增加关联数据库的字段 使用ForeignKey去关联
isbn = Column(String(15),nullable=False)
launched = Column(Boolean,default=False)#礼物有没有送出去
自定义基类
- 软删除 status = Column(SmallInteger,default=1)
- 自定义基类 继承(db.Model) 其他模块类直接继承Base就成
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import Column,Integer,SmallInteger
db = SQLAlchemy()
class Base(db.Model):
__abstract__ = True //防止Base被当成数据库表创建
status = Column(SmallInteger,default=1)
编写注册的校验
- 注册的校验
from wtforms import Form,StringField,IntegerField,PasswordField
from wtforms.validators import Length, DataRequired, Email, ValidationError
from app.models.user import User
class RegisterForm(Form):
email = StringField(validators=[DataRequired(),Length(8,64),
Email(message='电子邮箱不符合规范')])
password = PasswordField(validators=[DataRequired(
message='密码不能为空,请输入你的密码'),Length(6,32)])
nickname = StringField(validators = [
DataRequired(),Length(2,10,message="昵称至少需要两个字符,最多10个字符")])
- 动态赋值
class Base(db.Model):
__abstract__ = True
status = Column(SmallInteger,default=1)
def set_attrs(self,attrs_dict):
for key,value in attrs_dict.items():
if hasattr(self,key) and key != 'id':
setattr(self,key,value)
- auth.py
@web.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if request.method == "POST" and form.validate():
user = User()
user.set_attrs(form.data) //这里用了动态赋值 节省了很多代码
db.session.add(user)
db.session.commit()
redirect(url_for('web.login'))
return render_template("auth/register.html",form=form)
项目 处理明文密码加密
- 绝对不能在数据库以明文的形式存储注册的密码
- 先加密 后读取
from werkzeug.security import generate_password_hash,check_password_hash
class User(UserMixin,Base):
id = Column(Integer,primary_key = True)
nickname = Column(String(24),nullable = False)
phone_number = Column(String(18) ,unique = True)
_password = Column('password',String(128),nullable=False)//‘password’ 可以改写数据库表里对应的字段名称
email = Column(String(50),unique=True,nullable=False)
confirmed = Column(Boolean,default=False)
beans = Column(Float,default=0)
send_counter = Column(Integer,default=0)
receive_counter = Column(Integer,default=0)
wx_open_id = Column(String(50))
wx_name = Column(String(32))
@property 属性读取 //重点
def password(self):
return self._password
@password.setter 属性赋值 //重点
def password(self,raw):
self._password = generate_password_hash(raw)
#先赋值 后读取 也不太懂 到时候用的时候直接copy吧
注册接口的编写
@web.route('/register', methods=['GET', 'POST'])
def register():
form = RegisterForm(request.form)
if request.method == "POST" and form.validate():
user = User() 实例化User模块
user.set_attrs(form.data)
db.session.add(user) 添加数据
db.session.commit() 提交数据
redirect(url_for('web.login'))
return render_template("auth/register.html",form=form)
自定义验证器
from wtforms.validators import Length, DataRequired, Email, ValidationError
def validate_email(self,field):
if User.query.filter_by(email=field.data).first():
raise ValidationError('电子邮件已被注册!')
cookies
@web.route("/set/cookies")
def set_cookies():
response = make_response("Hello MR.7")
response.set_cookie('name',"MR.7",100) // key value 有效时间
return response
接下来实现登录接口
def check_password(self,raw):
return check_password_hash(self._password,raw)
#先加密 后对比的操作
login_user 用于登录以后加cookies
- 先下载模块 然后APP/init里初始化
from flask_login import LoginManager//
login_manager = LoginManager()//
def create_app():
app = Flask(__name__)
app.config.from_object('app.setting')
app.config.from_object('app.secure')
register_blueprint(app)
login_manager.init_app(app)//
db.init_app(app)
with app.app_context():
db.create_all()
return app
此时遇到了一个问题 cookies要获取用户的ID存入 login_user 将用户信息写入cookie
class User(UserMixin,Base): 继承UserMixin
@web.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
user = User.query.filter_by(email=form.email.data).first()
if user and user.check_password(form.password.data):
#login_user(user) //默认存入的是一次性的cookies
login_user(user,remeber=True) //永久保存cookies
pass
else:
flash('账号不存在或密码错误')
return render_template('auth/login.html',form=form)
访问权限路由控制 比如说gift页面必须是登录以后才能访问
- from flask_login import login_required
@web.route('/my/gifts')
@login_required //访问必须登录
def my_gifts():
return "My Gifts"
- model/user
@login_manager.user_loader
def get_user(uid):
return User.query.get(int(uid))
//暂时不知道加这个有毛用 但是不加还不行
解决一个问题 用户未登录在礼物的路由上 跳转登录 在返回到礼物的页面上
- 如果访问没有登录 跳转到登录页面 并且给与中文提示
def create_app():
app = Flask(__name__)
app.config.from_object('app.setting')
app.config.from_object('app.secure')
register_blueprint(app)
login_manager.init_app(app)
login_manager.login_view = 'web.login' //跳转到登录的代码
login_manager.login_message = '请先登录或注册' //提示的代码
db.init_app(app)
with app.app_context():
db.create_all()
return app
@web.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm(request.form)
if request.method == 'POST' and form.validate():
user = User.query.filter_by(email=form.email.data).first()
if user and user.check_password(form.password.data):
login_user(user)
next = request.args.get('next') //获取next后的值
if not next and not next.startswith('/'): next不存在 next不以/开头
next =url_for('web.index') 跳转url
return redirect(next)
else:
flash('账号不存在或密码错误')
return render_template('auth/login.html',form=form)
@web.route('/gifts/book/<isbn>')
@login_required
def save_to_gifts(isbn):
if current_user.can_save_to_list(isbn):
try:
gift = Gift()
gift.isbn = isbn
gift.uid = current_user.id
"""--------------------------"""
current_user.beans += current_app.config['BEANS_UPLOAD_ONE_BOOK']
db.session.add(gift)
db.session.commit()
except Exception as e:
db.session.rollback() #代码回滚
else:
flash("这本书已添加至你的赠送清单或已存在与你的心愿清单,请不要重复添加")