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("这本书已添加至你的赠送清单或已存在与你的心愿清单,请不要重复添加")
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容