Flask从零开始2

项目 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
没有登录 URL跳转到登录页面
@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("这本书已添加至你的赠送清单或已存在与你的心愿清单,请不要重复添加")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容