• flask框架初学-09-实践与巩固


    本章将以博客为例实践前几章学习的内容,讲解部分实例

    项目框架

    在这里插入图片描述

    首先看下ufrom的使用:

    app.py下关联CSRFProtect

    csrf = CSRFProtect(app=app)
    
    • 1

    在apps下的user下创建一个form.py文件定义登录表单输入格式

    import re
    
    from flask import session
    from flask_wtf import FlaskForm, RecaptchaField
    from flask_wtf.file import FileField, FileRequired, FileAllowed
    from wtforms import StringField,PasswordField
    from wtforms.validators import DataRequired, Length, ValidationError, EqualTo
    
    
    class UserForm(FlaskForm):
        name = StringField(label = 'name',validators=[DataRequired(),Length(min=6,max=12,message='用户名长度必须在6-12之间')])
        password = PasswordField(label = 'password',validators=[DataRequired(),Length(min=6,max=12,message='密码长度必须在6-12之间')])
        confirm_password = PasswordField(label = 'repassword',validators=[DataRequired(),Length(min=6,max=12,message='密码长度必须在6-12之间'),EqualTo('password','两次密码不一致')])
        phone = StringField(label="手机号码",validators=[DataRequired(),Length(min=11,max=11,message="手机长度必须为11位")])
        icon = FileField(label="用户头像",validators=[FileRequired(),FileAllowed(['jpg','png','gift'],message="必须是图片文件格式")])
        recaptcha = RecaptchaField(label="验证码")
        recaptchabyself = StringField(label='验证码')
    
        def validate_recaptchabyself(self,data):
            input_code = data.data
            code = session.get('valid')
            if input_code.lower() != code.lower():
                raise ValidationError("验证码错误!")
    
        # 自定义方法,必须要以validate_开头
        def validate_name(self,data):
            print('--------->',type(self.name))
            print('========>',type(data))
            if self.name.data[0].isdigit():
                raise ValidationError('用户名不能以数字开头')
    
        def validate_phone(self,data):
            phone = data.data
            if not re.search(r'^1[35678]\d{9}$',phone):
                raise ValidationError("手机格式错误!")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    然后再user下的views中需要表单验证的方法下实例化UserForm()表单

    @users_bp.route('/testForm',methods=['GET','POST'])
    def testForm():
        uform = UserForm()
        if uform.validate_on_submit():
            print(uform.name)
            print(uform.password)
            name = uform.name.data
            password = uform.password.data
            phone = uform.phone.data
            icon = uform.icon.data
            filename = secure_filename(icon.filename)
            BASE_DIR = os.path.dirname(os.path.abspath(__file__))
            STATIC_DIR = os.path.join(BASE_DIR,'static')
            UPLOAD_DIR = os.path.join(STATIC_DIR,'upload')
            icon.save(os.path.join(UPLOAD_DIR,filename))
            return '提交成功!'
        return render_template('formtest.html',uform)
    
    
    # from与bootstrap结合使用
    @users_bp.route('/user',methods=['GET','POST'])
    def boot_form_user():
        uform = UserForm()
        return render_template('from_bootstrap.html',uform=uform)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    最后在html中使用

    formtest.html

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <style>
            p span{
                font-size: 14px;
                color: red;
            }
        style>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">script>
    head>
    <body>
        <form action="" method="post" enctype="multipart/form-data">
            {{ uform.csrf_token }}
            <p>{{ uform.name.label }}:{{ uform.name }}<span>{% if uform.name.errors %}{{ uform.name.errors.0 }}{% endif %}span>p>
            <p>{{ uform.password.label }}:{{ uform.password }}<span>{% if uform.password.errors %}{{ uform.password.errors.0 }}{% endif %}span>p>
            <p>{{ uform.confirm_password.label }}:{{ uform.confirm_password }}<span>{% if uform.confirm_password.errors %}{{ uform.confirm_password.errors.0 }}{% endif %}span>p>
            <p>{{ uform.phone.label }}:{{ uform.phone }}<span>{% if uform.phone.errors %}{{ uform.phone.errors.0 }}{% endif %}span>p>
            <p>{{ uform.icon.label }}:{{ uform.icon }}<span>{% if uform.icon.errors %}{{ uform.icon.errors.0 }}{% endif %}span>p>
            <p>{{ uform.recaptcha.label }}:{{ uform.recaptcha }}<span>{% if uform.recaptcha.errors %}{{ uform.recaptcha.errors.0 }}{% endif %}span>p>
            <p>{{ uform.recaptchabyself.label }}:{{ uform.recaptchabyself }}<img src="{{ url_for('users.get_image') }}" alt="" id="img">
            <p>{% if uform.recaptcha.errors %}{{ uform.recaptcha.errors.0 }}{% endif %}p>
            <p><input type="submit" value="提交"> p>
        form>
    <script>
        $('#img').vlivk(function(){
            $(this).attr('src',"{{ url_for('get_image') }}?ran="+Math.random());
        })
    script>
    
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    form_bootstrap.html

    {% extends 'bootstrap/base.html'%}
    {% import 'bootstrap/wtf.html' as wtf %}
    {% block styles %}
      {{ super() }}
    {% endblock %}
    
    {% block content %}
      <form action="{{ url_for('hello_word') }}" method="post" enctype="multipart/form-data">
        {{ uform.csrf_token }}
        <p>{{ wtf.quick_form( uform, buttom_map = {'submit_button':'primary'}, horizontal_columns=('lg',5,2) ) }}p>
        <p>{{ wtf.form_field(uform.name) }}p>
      form>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    接下来进入正文,这里我们会提到两个模型:article、user,将围绕这两个模块构建一个简单的博客系统,包含增删改查操作,以及一些复杂关系关联等。

    user的模型对象:

    from datetime import datetime
    
    from exts import db
    
    
    class User(db.Model):
        id = db.Column(db.Integer,primary_key = True,autoincrement = True)
        username = db.Column(db.String(15),unique=True,nullable=False)
        password = db.Column(db.String(256),nullable=False)
        phone = db.Column(db.String(11),nullable=False,unique= True)
        email = db.Column(db.String(30))
        icon = db.Column(db.String(100))
        isdelete = db.Column(db.Boolean,default=False)
        rdatetime = db.Column(db.DateTime,default = datetime.now())
        articles = db.relationship('Article',backref='user')
        comments = db.relationship('Comment',backref='user')
    
        def __str__(self):
            return self.username
    
    class Photo(db.Model):
        id = db.Column(db.Integer,primary_key = True,autoincrement = True)
        photo_name = db.Column(db.String(50),nullable=False)
        photo_datatime = db.Column(db.DateTime,default=datetime.now())
        user_id = db.Column(db.Integer,db.ForeignKey('user.id'))
    
        def __str__(self):
            return self.photo_name
    
    class AboutMe(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        content = db.Column(db.BLOB,nullable=False)
        pdatetime = db.Column(db.DateTime, default=datetime.now())
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'),unique=True)
        user = db.relationship('User', backref='about')
    
        def __str__(self):
            return self.content
    
    
    class MessageBoard(db.Model):
        id = db.Column(db.Integer, primary_key=True, autoincrement=True)
        content = db.Column(db.String(256), nullable=False)
        mdatetime = db.Column(db.DateTime, default=datetime.now())
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
        user = db.relationship('User', backref='messages')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    article的模型对象:

    from datetime import datetime
    
    from exts import db
    
    class Article_type(db.Model):
        id = db.Column(db.Integer,primary_key=True, autoincrement=True)
        type_name = db.Column(db.String(20),nullable=False)
        articles = db.relationship('Article',backref='articletype')
    
    
    class Article(db.Model):
        id = db.Column(db.Integer,primary_key=True, autoincrement=True)
        title = db.Column(db.String(50),nullable=False)
        content = db.Column(db.Text,nullable=False)
        pdatetime = db.Column(db.DateTime,default=datetime.now())
        click_num = db.Column(db.Integer,default=0)
        save_num = db.Column(db.Integer,default=0)
        love_num = db.Column(db.Integer,default=0)
        # 外键 同步到数据库的外键关系
        user_id = db.Column(db.Integer,db.ForeignKey('user.id'),nullable=False)
        # 可在user/models.py中添加 articles = db.relationship('Article',backref='user')
        # user = db.relationship('User',backref='articles')
        type_id = db.Column(db.Integer,db.ForeignKey('article_type.id'))
        comments = db.relationship('Comment',backref='article')
    
    
    class Comment(db.Model):
        # 自定义表的名字
        # __tablename__ = 'comment'
    
        id = db.Column(db.Integer,primary_key=True,autoincrement=True)
        comment = db.Column(db.String(255),nullable=False)
        user_id = db.Column(db.Integer,db.ForeignKey('user.id'))
        article_id = db.Column(db.Integer,db.ForeignKey('article.id'))
        cdatetime = db.Column(db.DateTime,default = datetime.now())
    
        def __str__(self):
           return self.comment
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    user的视图控制器views

    import hashlib
    import logging
    import os
    import time
    from io import BytesIO
    
    from flask import Blueprint, render_template, request, url_for, jsonify, session, g, make_response, flash, app
    from flask_wtf import csrf
    from werkzeug.security import generate_password_hash, check_password_hash
    from werkzeug.utils import redirect, secure_filename
    
    from apps.article.models import Article_type, Article
    from apps.user.form import UserForm
    from apps.user.models import User, Photo, AboutMe, MessageBoard
    from apps.user.smssend import SmsSendAPIDemo
    from apps.utils.util import upload_qiniu, delete_qiniu, user_type, sendMessage, generate_image
    from exts import db, cache
    from settings import Config
    
    users_bp = Blueprint('users',__name__,url_prefix='/users')
    
    # 访问以下url需要已登录状态
    required_login_list = ['/users/center',
                           '/users/change',
                           '/users/publish',
                           '/users/upload_photo',
                           '/users/photo_del',
                           '/articles/add_comment',
                           '/users/aboutme',
                           '/users/showabout']
    
    @users_bp.before_app_first_request
    def first_request():
        print('before_app_first_request')
        if request.path in required_login_list:
            print("需要验证用户的登录情况!")
    
    
    @users_bp.before_app_request
    def before_request1():
        print('before_app_request',request.path)
        if request.path in required_login_list:
            id = session.get('uid')
            print('------>',id)
            if not id:
                uform = UserForm()
                return render_template('user/login.html',uform=uform)
            else:
                user = User.query.get(id)
                # g对象 本次请求的对象
                g.user = user
                print(g.user.username)
    
    @users_bp.after_app_request
    def after_request_test(response):
        print('after_app_request')
        response.set_cookie('a','bbbb',max_age=19)
        return response
    
    @users_bp.teardown_app_request
    def teardown_request_test(response):
        print('teardown_app_request')
    
    
    # 自定义过滤器
    @users_bp.app_template_filter('cdecode')
    def content_decode(content):
        content = content.decode('utf-8')
        return content[:200]
    
    # 自定义过滤器
    @users_bp.app_template_filter('cdecode1')
    def content_decode1(content):
        content = content.decode('utf-8')
        return content
    
    # 首页
    @users_bp.route('/')
    @cache.cached(timeout=50)
    def index():
         # 1、cookie的获取
        # uid = request.cookies.get('uid',None)
    
        # # 2、session的获取,session默认
        # uid = session.get('uid')
        user,types = user_type()
        page = int(request.args.get('page',1))
        print(page)
        # 判断是否存在检索词汇
        search = request.args.get('search','')
        # 有检索词汇
        if search:
            # 进行检索contains
            pagination = Article.query.filter(Article.title.contains(search)).order_by(-Article.pdatetime).paginate(page, per_page=1)
        else:
            # 获取文章列表
            pagination = Article.query.order_by(-Article.pdatetime).paginate(page,per_page=1)
        print(pagination.items)
        print(pagination.page)  # 当前页码数
        print(pagination.prev_num)  # 当前的前一个页码数
        print(pagination.next_num)  # 当前的后一页的页码数
        print(pagination.has_next)
        print(pagination.has_prev)
        print(pagination.pages) # 总共有几页
        print(pagination.total) # 总的记录条数
        params = {
            'user': user,
            'types': types,
            'pagination': pagination,
            'search': search
        }
        # 模拟延时
        for i in range(10):
            time.sleep(0.5)
        return render_template('user/index.html',**params)
    
    # 用户注册
    @users_bp.route('/register',methods=['POST','GET'])
    def register():
        if request.method == 'POST':
            username = request.form.get('username')
            password = request.form.get('password')
            repassword = request.form.get('repassword')
            phone = request.form.get('phone')
            email = request.form.get('email')
            if password == repassword:
                user = User()
                user.username = username
                # user.password = hashlib.md5(password.encode('utf-8')).hexdigest()
                # 使用自带的函数实现加密:generate_password_hash
                user.password = generate_password_hash(password)
                user.phone = phone
                user.email = email
                db.session.add(user)
                db.session.commit()
                return redirect(url_for('users.index'))
            return render_template('user/register.html',msg='用户确认密码不正确!')
        return render_template('user/register.html')
    
    # 手机号码验证
    @users_bp.route('/checkphone',methods=['POST','GET'])
    def check_phone():
        phone = request.args.get('phone')
        user = User.query.filter(User.phone == phone).all()
        if user:
            return jsonify(code=400,msg='此号码已被注册')
        else:
            return jsonify(code=200,msg='此号码可用')
    
    # 登录
    @users_bp.route('/login',methods=['POST','GET'])
    def login():
        print("我看你进来了没有")
        if request.method == 'POST':
            f = request.args.get('f')
            # 手机密码登录
            if f == '1':
                username = request.form.get('username')
                password = request.form.get('password')
                users = User.query.filter(User.username == username).all()
                for user in users:
                    # check_password_hash(加密后的密码, 传入的密码) 如果Flag=True表示匹配
                    Flag = check_password_hash(user.password, password)
                    if Flag:
                        '''
                        # 1、cookie实现机制
                        response = redirect(url_for('users.index'))
                        response.set_cookie('uid',str(user.id),max_age=1800)
                        return response
                        '''
                        # 2、session实现机制,session当成字典使用
                        session['uid'] = user.id
                        return redirect(url_for('users.index'))
                    else:
                        return render_template('user/login.html',msg='用户名或密码错误!')
            # 手机验证码登录
            elif f == '2':
                phone = request.form.get('phone')
                code = request.form.get('code')
                # session中获取验证码
                # valid_code = session.get('phone')
                # redis缓存中获取验证码
                valid_code = cache.get(phone)
                print(valid_code)
                user = User.query.filter(User.phone == phone).first()
                if user:
                    if code == valid_code:
                        session['uid'] = user.id
                        return redirect(url_for('users.index'))
                    else:
                        return render_template('user/login.html', msg='验证码有误!')
                else:
                    return render_template('user/login.html',msg='手机号码未注册!')
        else:
            return render_template('user/login.html')
    
    # 退出登录
    @users_bp.route('/logout')
    def logout():
        '''
        # 1、cookie方式
        response = redirect(url_for('user.index'))
        # 通过response对象的delete_cookie(key),key就是要删除的cookie的key
        response.delete_cookie('uid')
        return response
        '''
        # 2、session方式
        # del session['uid']
        session.clear()
    
        return redirect(url_for('users.index'))
    
    # 发送短信
    @users_bp.route('/sendMsg')
    def send_message():
        phone = request.args.get('phone')
        user = User.query.filter(User.phone==phone).first()
        print(user.username)
        if user:
            ret,code = sendMessage(phone)
            '''
             # session中存储验证码
            session['phone'] = '122417'
            return jsonify(cood=200,msg='短信发送成功!')
            '''
    
            if ret is not None:
                if ret["code"] == 200:
                    # taskId = ret["data"]["taskId"]
                    # print("taskId = %s" % taskId)
                    # session[phone] = '122417'
    
                    # cache.set(key,value,timeout=second)
                    # 将验证码存入redis,并设置有效时间为180s
                    cache.set(phone, code, timeout=180)
                    return jsonify(cood=200,msg='短信发送成功!')
                else:
                    print ("ERROR: ret.code=%s,msg=%s" % (ret['code'], ret['msg']))
                    return jsonify(cood=200, msg='短信发送失败!')
        else:
            return render_template('user/login.html', msg='手机号未注册!')
    
    # 用户中心
    @users_bp.route('/center')
    def center():
        user, types = user_type()
        photos = Photo.query.filter(Photo.user_id == g.user.id).all()
        return render_template('user/center.html',user=g.user,types=types,photos=photos)
    
    
    # 图片的扩展名
    ALLOWWD_EXTENDIONS = ['jpg','png','gif','bmp']
    
    # 修改信息
    @users_bp.route('/change',methods=['POST','GET'])
    def user_change():
        if request.method == 'POST':
            username = request.form.get('username')
            phone = request.form.get('phone')
            email = request.form.get('email')
            # 图片必须使用request.files.get()获取
            icon = request.files.get('icon')
            # 查询一下手机号码
            users = User.query.all()
            for user in users:
                if user.phone == phone:
                    return render_template('user/center.html',user=g.user,msg='此号码已被注册!')
                else:
                    # 属性:filename 用户获取文件的名字
                    # 方法:save(保存路径)
                    icon_name = icon.filename
                    suffix = icon_name.rsplit('.')[-1]
                    if suffix in ALLOWWD_EXTENDIONS:
                        # 保存文件名是符合python的命名规则
                        icon_name = secure_filename(icon_name)
                        file_path = os.path.join(Config.UPLOAD_ICON_DIR, icon_name)
                        icon.save(file_path)
                        user = g.user
                        user.username = username
                        user.phone = phone
                        user.email = email
                        path = 'upload/icon/'
                        user.icon = os.path.join(path,icon_name)
                        print('------------->',user.icon)
                        db.session.commit()
                        return redirect(url_for('users.center'))
                    else:
                        return render_template('user/center.html', user=g.user, msg='图片扩展名必须为:jpg,png,gif,bmp')
        return render_template('user/center.html',user=g.user)
    
    
    # 上传照片
    @users_bp.route('/upload_photo',methods=['GET','POST'])
    def upload_photo():
        # 获取上传的内容
        photo = request.files.get('photo')
        ret,info = upload_qiniu(photo)
        if info.status_code == 200:
            photo = Photo()
            photo.photo_name = ret['key']
            photo.user_id = g.user.id
            db.session.add(photo)
            db.session.commit()
            return '上传成功!'
        else:
            return '上传失败!'
    
    # 展示图片
    @users_bp.route('myphoto')
    def myphoto():
        page = int(request.args.get('page',1))
        # 分页
        photos = Photo.query.paginate(page=1,per_page=3)
        user, types = user_type()
        return render_template('user/myphoto.html',photos=photos,user=user,types=types)
    
    # 删除相册图片
    @users_bp.route('/photo_del',methods=['GET','POST'])
    def photo_del():
        pid = request.args.get('pid')
        photo = Photo.query.get(pid)
        filename = photo.photo_name
        info = delete_qiniu(filename)
        if info.status_code == 200:
            db.session.delete(photo)
            db.session.commit()
            return redirect('users.user_center')
        else:
            return render_template('500.html',err_msg='删除相册失败!')
    
    # 关于用户介绍添加
    @users_bp.route('/aboutme',methods=['GET','POST'])
    def about_me():
        content = request.form.get('about')
        try:
            aboutme = AboutMe()
            aboutme.content = content.encode('utf-8')
            aboutme.user_id = g.user.id
            db.session.add(aboutme)
            db.session.commit()
        except Exception as err:
            return redirect(url_for('users.user_center'))
        else:
            return render_template('user/aboutme.html',user=g.user)
    
    @users_bp.route('/showabout')
    def show_about():
        user, types = user_type()
        return render_template('user/aboutme.html',user=g.user,types=types)
    
    # 展示错误页
    @users_bp.route('/error')
    def test_error():
        referer = request.headers.get('Referer',None)
        return render_template('500.html',referer=referer)
    
    # 留言板
    @users_bp.route('/board',methods=['GET','POST'])
    def show_board():
        user, types = user_type()
        uid= user.id
        # 查询所有的留言内容
        page = int(request.args.get('page',1))
        boardes = MessageBoard.query.filter(MessageBoard.user_id == uid).order_by(-MessageBoard.mdatetime).paginate(page=page,per_page=3)
        if request.method == 'POST':
            content = request.form.get('board')
            msg_board = MessageBoard()
            msg_board.content = content
            if uid:
                msg_board.uid = uid
            db.session.add(msg_board)
            db.session.commit()
            return redirect(url_for('users.show_board'))
    
        return render_template('user/board.html',user=g.user,boardes=boardes)
    
    # 删除留言
    @users_bp.route('/board_del')
    def delete_board():
        bid = request.agrs.get('bid')
        if bid:
            msgboard = MessageBoard.query.get(bid)
            db.session.delete(msgboard)
            db.session.commit()
        return redirect(url_for('users.user_center'))
    
    @users_bp.route('/testForm',methods=['GET','POST'])
    def testForm():
        uform = UserForm()
        if uform.validate_on_submit():
            print(uform.name)
            print(uform.password)
            name = uform.name.data
            password = uform.password.data
            phone = uform.phone.data
            icon = uform.icon.data
            filename = secure_filename(icon.filename)
            BASE_DIR = os.path.dirname(os.path.abspath(__file__))
            STATIC_DIR = os.path.join(BASE_DIR,'static')
            UPLOAD_DIR = os.path.join(STATIC_DIR,'upload')
            icon.save(os.path.join(UPLOAD_DIR,filename))
            return '提交成功!'
        return render_template('formtest.html',uform)
    
    @users_bp.route('/image')
    def get_image():
       im,code = generate_image()
       # 将image对象转成二进制
       buffer = BytesIO()
       im.save(buffer,"JPEG")
       buf_bytes = buffer.getvalue()
       # 保存到session中
       session['valid'] = code
       response = make_response(buf_bytes)
       response.headers['Content-Type'] = 'image/jpg'
       return response
    
    # from与bootstrap结合使用
    @users_bp.route('/user',methods=['GET','POST'])
    def boot_form_user():
        uform = UserForm()
        return render_template('from_bootstrap.html',uform=uform)
    
    # flash
    @users_bp.route('/flush',methods=['GET','POST'])
    def test_flush():
        if request.method == 'POST':
            username = request.form.get('username')
            if username == 'admin':
                flash('登录成功!','info')
                flash(username,'warning')
                flash('hahha', 'error')
                return render_template('index.html')
            else:
                app.logger.debug('这是一个debug测试')
                app.logger.warning('这是一个warning测试')
                app.logger.error('这个是一个error测试')
        return render_template('flushtest.html')
    
    logger = logging.getLogger('app')
    logger.setLevel(level=logging.WARNING)
    handler = logging.FileHandler("log2.txt")
    handler.setLevel(logging.INFO)
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    
    @users_bp.route('/logger')
    def logger_test():
        logger.warning("首页的警告!!!!!!")
        app.logger.warning('首页警告2!!!!!')
        return render_template('')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453

    article的视图控制器views

    '''
    Author: 梁雅馨
    CreateTime: 
    descript: 
    '''
    
    from flask import Blueprint, request, g, url_for, render_template, jsonify, session
    from werkzeug.utils import redirect
    
    from apps.article.models import Article, Article_type, Comment
    from apps.user.models import User
    from exts import db
    
    articles_bp = Blueprint('articles',__name__,url_prefix='/articles')
    
    # 访问以下url需要已登录状态
    required_login_list = ['/articles/publish',
                           '/articles/love',
                           '/articles/save',
                           '/articles/add_comment']
    
    @articles_bp.before_app_first_request
    def first_request():
        print('before_app_first_request')
        if request.path in required_login_list:
            print("需要验证用户的登录情况!")
    
    
    @articles_bp.before_app_request
    def before_request1():
        print('before_app_request',request.path)
        if request.path in required_login_list:
            id = session.get('uid')
            print('------>',id)
            if not id:
                return render_template('user/login.html')
            else:
                user = User.query.get(id)
                # g对象 本次请求的对象
                g.user = user
                print(g.user.username)
    
    # 自定义过滤器
    @articles_bp.app_template_filter('cdecode')
    def content_decode(content):
        content = content.decode('utf-8')
        return content
    
    # 发布文章
    @articles_bp.route('/publish',methods=['POST','GER'])
    def publish_article():
        if request.method == 'post':
            title = request.form.get('title')
            type_id = request.method.get('type')
            content = request.form.get('content')
            article = Article()
            article.title = title
            article.type_id = type_id
            article.content = content
            article.user_id = g.user.id
            db.session.add(article)
            db.session.commit()
            return redirect(url_for('users.index'))
    
    # 展示文章详情
    @articles_bp.route('/detail')
    def articles_detail():
        # 通过id获取文章
        id= request.args.get('aid')
        print(id)
        article = Article.query.get(id)
    
        # 获取文章分类
        # types = Article_type.query.all(0)
        # 登录用户
        user_id = session.get('uid')
        user = None
        if user_id:
            user = User.query.get(user_id)
        page = int(request.args.get('page',1))
        comment = Comment.query.filter(Comment.article_id == id).order_by(-Comment.cdatetime).paginate(page=page,per_page=5)
        return render_template('articles/detail.html',article=article,user=user,comment=comment)
    
    # 收藏
    @articles_bp.route('/love')
    def articles_love():
        article_id = request.args.get('aid')
        tag = request.args.get('tag')
        article = Article.query.get(article_id)
        if tag == '1':
            article.love_num -= 1
        else:
            article.love_num += 1
        db.session.commit()
        return jsonify(num = article.love_num)
    
    # 点赞
    @articles_bp.route('/save')
    def articles_save():
        article_id = request.args.get('aid')
        tag = request.args.get('tag')
        article = Article.query.get(article_id)
        if tag == '1':
            article.save_num -= 1
        else:
            article.save_num += 1
    
        db.session.commit()
        return jsonify(num=article.save_num)
    
    # 发表文章评论
    @articles_bp.route('/add_comment',methods=['POST','GER'])
    def article_comment():
        if request.method == 'POST':
            comments = request.form.get('comment')
            user_id = g.user.id
            article_id = request.form.get('aid')
            print(article_id)
            comment =Comment()
            comment.comment = comments
            comment.article_id = article_id
            comment.user_id = user_id
            db.session.add(comment)
            db.session.commit()
            return redirect(url_for('articles.articles_detail')+"?aid="+article_id)
        return redirect(url_for('user.index'))
    
    # 文章分类检索
    @articles_bp.route('/type_search')
    def type_search():
        uid = session.get('uid')
        user = None
        if uid:
            user = User.query.get(uid)
        # 文章分类获取
        types = Article_type.query.all()
        # 获取tid
        tid = int(request.args.get('tid',1))
        page = int(request.args.get('page',1))
        type = Article_type.query.get(tid)
        articles = Article.query.filter(Article.articletype == type).order_by(-Article.pdatetime).paginate(page=page,per_page=1)
    
        return render_template('articles/article_type.html',user=user,types=types,type=type,articles=articles)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    工具方法 smssend.py

    import hashlib
    from hashlib import md5
    import json
    import random
    import time
    import urllib
    import urllib.request
    
    
    class SmsSendAPIDemo(object):
        API_URL = "https://sms.dun.163.com/v2/sendsms"
        VERSION = "v2"
    
        def __init__(self, secret_id, secret_key, business_id):
            """
            Args:
                secret_id (str) 产品密钥ID,产品标识
                secret_key (str) 产品私有密钥,服务端生成签名信息使用
                business_id (str) 业务ID,易盾根据产品业务特点分配
            """
            self.secret_id = secret_id
            self.secret_key = secret_key
            self.business_id = business_id
    
        def gen_signature(self, params=None):
            """生成签名信息
            Args:
                params (object) 请求参数
            Returns:
                参数签名md5值
            """
            buff = ""
            for k in sorted(params.keys()):
                buff += str(k) + str(params[k])
            buff += self.secret_key
            return hashlib.md5(buff.encode("utf-8")).hexdigest()
    
        def send(self, params):
            """请求易盾接口
            Args:
                params (object) 请求参数
            Returns:
                请求结果,json格式
            """
            params["secretId"] = self.secret_id
            params["businessId"] = self.business_id
            params["version"] = self.VERSION
            params["timestamp"] = int(time.time() * 1000)
            params["nonce"] = int(random.random() * 100000000)
            params["signature"] = self.gen_signature(params)
    
            try:
    
                params = urllib.parse.urlencode(params)
                params = params.encode('utf-8')
                request = urllib.request.Request(self.API_URL, params)
                content = urllib.request.urlopen(request, timeout=5).read()
                return json.loads(content)
                # response = request.post(self.API_URL, data=params)
                # return response.json()
            except Exception as ex:
                print("调用API接口失败:", str(ex))
    
    
    if __name__ == "__main__":
        """示例代码入口"""
        SECRET_ID = "**********"  # 产品密钥ID,产品标识
        SECRET_KEY = "*************"  # 产品私有密钥,服务端生成签名信息使用,请严格保管,避免泄露
        BUSINESS_ID = "**************"  # 业务ID,易盾根据产品业务特点分配
        api = SmsSendAPIDemo(SECRET_ID, SECRET_KEY, BUSINESS_ID)
    
        params = {
            "mobile": "15010185644",
            "templateId": "10084",
            "paramType": "json",
            "params": "{'code':200','time':'20211224'}"
            # 国际短信对应的国际编码(非国际短信接入请注释掉该行代码)
            # "internationalCode": "对应的国家编码"
        }
        ret = api.send(params)
        if ret is not None:
            if ret["code"] == 200:
                taskId = ret["data"]["taskId"]
                print("taskId = %s" % taskId)
            else:
                print ("ERROR: ret.code=%s,msg=%s" % (ret['code'], ret['msg']))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    utils下的util.py

    # -*- coding: utf-8 -*-
    # flake8: noqa
    import os
    from random import random
    
    import requests
    from PIL import ImageFilter
    from PIL.Image import Image
    from PIL.ImageDraw import ImageDraw
    from PIL.ImageFont import ImageFont
    from PIL._imaging import font
    from flask import session
    from qiniu import Auth, put_file, etag
    from qiniu import BucketManager
    
    from apps.article.models import Article_type
    from apps.user.models import User
    from apps.user.smssend import SmsSendAPIDemo
    from settings import Config
    
    access_key = 'KWkj4za9qp5KYy7VDzkLrxC6OBJvZvtuO-28pFoB'
    secret_key = 'aiLWEJDBPUR8Be_hv-nlg-NhIh3kusH5ch-wjTbN'
    # 要上传的空间
    bucket_name = 'mublog2022'
    
    def user_type():
        user_id = session.get('uid')
        user = None
        if user_id:
            user = User.query.get(user_id)
        types = Article_type.query.all()
        return user,types
    
    def sendMessage(phone):
        SECRET_ID = "33fc0b00c3505c3ed4c710f965e309fa"  # 产品密钥ID,产品标识
        SECRET_KEY = "f3d9dac4fa83272242411e2f1a6b1ae0"  # 产品私有密钥,服务端生成签名信息使用,请严格保管,避免泄露
        BUSINESS_ID = "6288c6bfb7764a24a6cc226b2ffb61a8"  # 业务ID,易盾根据产品业务特点分配
        api = SmsSendAPIDemo(SECRET_ID,SECRET_KEY,BUSINESS_ID)
        # secret_pair = SecretPair(SECRET_ID,SECRET_KEY)
        # api = SmsSendAPIDemo(BUSINESS_ID,secret_pair)
        # 随机产生验证码
        code = ""
        for i in range(4):
            ran = random.randint(0,9)
            code += str(ran)
        params = {
            "mobile": phone,
            "templateId": "10084",
            "paramType": "json",
            "params": {'code':code,'time':'20211224'}
            # 国际短信对应的国际编码(非国际短信接入请注释掉该行代码)
            # "internationalCode": "对应的国家编码"
        }
        ret = api.send(params)
        return ret,code
    
    
    
    # 上传本地文件
    def upload_qiniu(filestorage):
        # 初始化Auth状态
        q = Auth(access_key, secret_key)
        # 初始化BucketManager
        bucket = BucketManager(q)
        # 获取文件名
        filename = filestorage.filename
        # 重新拼接成一个不重复的文件名
        ran = random.randint(1,1000)
        suffix = filename.rsplit('.')[-1]
        key = filename.rsplit('.')[0]+ '_' +str(ran) + '.' +suffix
    
        #生成上传 Token,可以指定过期时间等
        token = q.upload_token(bucket_name, key, 3600)
        #要上传文件的本地路径
        # localfile = os.path.join(Config.UPLOAD_ICON_DIR,phone_name)
        ret, info = put_file(token, key, filestorage.read(), version='v2')
        # print(info)
        assert ret['key'] == key
        assert ret['hash'] == etag(filestorage.read())
        return ret,info
    
    def delete_qiniu(key):
        # 初始化Auth状态
        q = Auth(access_key, secret_key)
        # 初始化BucketManager
        bucket = BucketManager(q)
        # 删除bucket_name 中的文件 key
        ret, info = bucket.delete(bucket_name, key)
        print(info)
        assert ret == {}
        return info
    
    # 获取上传文件
    def GetImage(phone_name):
        # 初始化Auth状态
        q = Auth(access_key, secret_key)
        # 初始化BucketManager
        bucket = BucketManager(q)
        #获取文件的状态信息
        ret, info = bucket.stat(bucket_name, phone_name)
        print(info)
        assert 'hash' in ret
    
    
    # 私有空间下载
    def download(bucket_domain,phone_name):
        # 初始化Auth状态
        q = Auth(access_key, secret_key)
        # 初始化BucketManager
        bucket = BucketManager(q)
        # 有两种方式构造base_url的形式
        base_url = 'http://%s/%s' % (bucket_domain, phone_name)
        # 或者直接输入url的方式下载
        base_url = 'http://domain/key'
        # 可以设置token过期时间
        private_url = q.private_download_url(base_url, expires=3600)
        print(private_url)
        r = requests.get(private_url)
        assert r.status_code == 200
    
    # 获取随机颜色
    def get_random_color(length):
        return (random.randint(0,255),random.ranint(0,255),random.randint(0,255))
    # 生成图片
    def generate_image(length):
        s = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRTSUVWXYZ1234567890'
        size = (130,50)
        # 创建画布
        im = Image.new('RGB',size,color=get_random_color())
        # 创建字体
        ImageFont.truetype('font/segoerp.ttf',size=35)
        # 创建ImageDraw对象
        draw = ImageDraw.Draw(im)
        code = ''
        # 绘制验证码
        for i in random(length):
            c = random.choice(s)
            code += c
            # draw.text(坐标位置,绘制谁,用什么颜色,字体)
            draw.text((5+ random.randint(4,7) + 25 * i, random.randint(1,4)),
                      text=c,fill=get_random_color(),
                      font=font)
            # 绘制干扰线
            for i in range(8):
                x1 = random.randomint(0,130)
                y1 = random.randomint(0,50/2)
                x2 = random.randomint(0, 130)
                y2 = random.randomint(50/2, 130)
                draw.line(((x1,y1),(x2,y2)),fill=get_random_color())
        im = im.filter(ImageFilter.EDGE_ENHANCE)
        return im, code
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151

    部分html视图代码,其余html文件可根据自身要求编写

    register.html

    {% extends "base.html" %}
    {% block title %}用户注册{% endblock %}
    {% block styles %}
        {{ super() }}
        <style>
            #container{
                width: 1000px ;
                height: 600px;
                margin: 20px auto;
                padding-top: 20px;
            }
        style>
    {% endblock %}
    
    {% block newcontent %}
        <div id="container">
            <h1 class="col-sm-offset-4 col-sm-10">用户注册h1>
            <p class="col-sm-offset-4 col-sm-10" style="color:red">{{ msg }}p>
            <form class="form-horizontal" method="post" action="{{ url_for('users.register') }}">
                <div class="form-group">
                    <label for="inputUsername" class="col-md-2 control-label">用户名label>
                    <div class="col-md-6">
                        <input type="text" class="form-control" id="inputUsername" name='username' placeholder="username">
                    div>
                div>
                <div class="form-group">
                    <label for="inputPassword" class="col-md-2 control-label">密码label>
                    <div class="col-md-6">
                        <input type="password" class="form-control" id="inputPassword" name="password" placeholder="password">
                    div>
                div>
                <div class="form-group">
                    <label for="inputConfirm" class="col-md-2 control-label">确认密码label>
                    <div class="col-md-6">
                        <input type="password" class="form-control" id="inputConfirm" name="repassword" placeholder="confirm password">
                    div>
                div>
                <div class="form-group">
                    <label for="inputPhone" class="col-md-2 control-label">手机号码label>
                    <div class="col-md-6">
                        <input type="password" class="form-control" id="inputPhone" name="phone" placeholder="phone number"><span id="">span>
                    div>
                div>
                <div class="form-group">
                    <label for="inputEmail" class="col-md-2 control-label">邮箱label>
                    <div class="col-md-6">
                        <input type="email" class="form-control" id="inputEmail" name="email" placeholder="Email">
                    div>
                div>
                <div class="form-group">
                    <div class="col-sm-offset-3 col-sm-12">
                        <button type="submit" class="btn btn-primary col-sm-3" >    button>
                    div>
                div>
            form>
        div>
    {% endblock %}
    
    {# 添加js脚本 #}
    {% block scripts %}
        {{ super() }}
        <script>
            $('#inputPhone').blur(function(){
                let phone = $(this).val();
                let span_ele = $(this).next('span');
                if(phone.length==11){
                    span_ele.text('');
                    $.get('{{ url_for('users.check_phone') }}',{phone:phone},function(data){
                        console.log(data);
                        if(data.code!=200){
                            span_ele.css({'color':'#ff0011','font-size':'12px'});
                            span_ele.text('data.msg');
                    }
                })
                } else{
                    span_ele.css({'color':'#ff0011','font-size':'12px'});
                    span_ele.text('手机格式错误');
                }
    
            })
        script>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82

    login.html

    {% extends "base.html" %}
    {% block title %}用户登录{% endblock %}
    {% block styles %}
        {{ super() }}
        <style>
            #container{
                width: 1000px ;
                height: 600px;
                margin: 0px auto;
                padding-top: 30px;
            }
            #container h1 {
                text-align: center;
                margin-bottom: 50px;
            }
            #container form {
                margin: 0 auto;
            }
            #tab{
                font-size: 20px;
                text-align: left;
                padding-left: 170px;
                margin-bottom: 50px;
            }
            #tab span{
                display: inline-block;
                width: 120px;
                text-align: center;
                cursor: default;
                color: #f3f3f3;
            }
            #tips{
                color: red;
                font-size: 10px;
            }
            #btnCheck{
                width: 140px;
            }
        style>
    {% endblock %}
    {% block newcontent %}
        <div id="container">
            <h1 class="col-sm-offset-4 col-sm-10">用户登录h1>
            <div id="tab">
                <span>用户名/密码span> | <span>手机验证码span>
                <p id="tips">{{ msg }}p>
            div>
            <div class="logintab">
                <form class="form-horizontal" method="post" action="{{ url_for('users.login') }}?f=1">
                    <div class="form-group">
                        <label for="inputUsername" class="col-md-2 col-sm-offset-1 control-label">用户名label>
                        <div class="col-md-6">
                            <input type="text" class="form-control" id="inputUsername" name='username' placeholder="username">
                        div>
                    div>
                    <div class="form-group">
                        <label for="inputPassword" class="col-md-2 col-sm-offset-1 control-label">密码label>
                        <div class="col-md-6">
                            <input type="password" class="form-control" id="inputPassword" name="password" placeholder="password">
                        div>
                    div>
                    <div class="form-group">
                        <div class="col-sm-offset-3 col-sm-10">
                            <button type="submit" class="btn btn-primary col-sm-3" >    button>
                            <button type="submit" class="btn btn-primary col-sm-3" >    button>
                        div>
                    div>
                form>
            div>
            <div class="logintab">
                <form class="form-horizontal" method="post" action="{{ url_for('users.login') }}?f=2">
                    <div class="form-group">
                        <div class="col-md-6 col-md-offset-2">
                            <input type="text" class="form-control" id="inputPhone" name='phone' placeholder="输入手机号">
                        div>
                    div>
                    <div class="form-group">
                        <div class="col-md-4 col-md-offset-2">
                            <input type="text" class="form-control" id="inputCode" name="code" placeholder="输入验证码">
                        div>
                        <div class="col-md-2">
                            <input type="button" id="btnCheck" class="btn btn-info" value="发送验证码">
                        div>
                    div>
                    <div class="form-group">
                        <div class="col-md-offset-2 col-md-10">
                            <button type="submit" class="btn btn-primary col-sm-3" >    button>
                            <button type="submit" class="btn btn-primary col-sm-3" >    button>
                    div>
                    div>
                form>
            div>
    
        div>
    {% endblock %}
    {# 添加js脚本 #}
    {% block scripts %}
        {{ super() }}
        <script>
            $(function(){
                // 显示 | 隐藏 登录方式
                $(".logintab").hide();
                $(".logintab").first().show();
                $("#tab span").each(function(i){
                    $(this).click(function(){
                        $(".logintab").hide();
                        $(".logintab").eq(i).show();
                    })
                });
                // 发送验证码
                $('#btnCheck').click(function(){
                    let phone = $('#inputPhone').val();
                    let span_obj = $('#inputPhone').next('span');
                    if(phone && phone.length==11){
                        alert(phone)
                        // 发送ajax
                        $.get('{{ url_for('users.send_message') }}',{phone:phone},function(data){
                            if(data.code==200){
                                alert('短信发送成功,请注意查收!');
                            }else{
                                alert(data.msg);
                            }
                        });
                    }else{
                        span_obj.css({'color':'red','font-size':'12px'});
                        span_obj.text('必须输入11为手机号码')
                    }
                });
    
            })
        script>
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    index.html

    {% extends "base.html" %}
    {% block title %}博客首页{% endblock %}
    {% block styles %}
        {{ super() }}
        <style>
            #container{
                width: 1200px ;
                margin: 0 auto;
            }
            .article{
              width: 90%;
              margin: 20px auto;
              padding: 5px 10px;
              background-color: rgba(131,202,227,0.7);
              border-bottom: 1px solid Linen;
            }
    
            .article p {
                font-size: 14px;
                rgba(75,75,74,1.00);
            }
    
            .article h4 a {
                color: rgba(80,80,79,1.00);
            }
    
            .article h4 a:hover {
                color: black;
            }
    
            .article div span {
                margin-left: 20px;
            }
            .article div{
                margin-bottom: 18px;
            }
        </style>
    {% endblock %}
    
    {% block newcontent %}
        <div id="container">
            {% for article in pagination.items %}
                <div class="article">
                    <h4><a href="{{ url_for('articles.articles_detail')}}?aid={{ article.id }}">{{ article.title }}</a></h4>
                    <p>
                        <span>作者:{{ article.user.username }}</span>
                        <br>
                        <br>
                        <div>{{ article.content | safe }}</div>
                    </p>
                    <div>
                        <span style="margin-left:0">发布时间:{{ article.pdatetime }}</span>
                        <span>收藏:{{ article.save_num }}</span>
                    </div>
                </div>
            {% endfor %}
    <!--
            <div class="article"></div>
            <div class="article"></div>
            <div class="article"></div>
            <div class="article"></div>
            <div class="article"></div>
            -->
            <nav aria-label="Page navigation" class="col-md-offset-5">
                <ul class="pagination">
                    <li {% if not pagination.has_prev %} class="disabled" {% endif %}>
                        <a {% if pagination.has_prev %} href="{{ url_for('users.index') }}?page={{ pagination.prev_num }} " {% endif %} aria-label="Previous">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
    
                    <!--
                    <li {% if not pagination.has_prev %} class="disabled" {% endif %}>
                        <a href="{{ url_for('users.index') }}?page={{ pagination.prev_num }} " aria-label="Previous">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                    -->
                    {% for page_num in range(1,pagination.pages + 1) %}
                        <li {% if pagination.page== page_num %} class="active" {% endif %}><a href="{{url_for('users.index') }}?page={{ page_num }}">{{ page_num }}</a> </li>
                    {% endfor %}
                <!--    <li class="active"><a href="{{ url_for('users.index') }}?page=1">1 <span class="sr-only">(current)</span></a></li>
                    <li><a href="{{ url_for('users.index') }}?page=3">3 <span class="sr-only">(current)</span></a></li>
                    <li><a href="{{ url_for('users.index') }}?page=4">4 <span class="sr-only">(current)</span></a></li>   -->
    
                    <li {% if not pagination.has_next %} class="disabled" {% endif %}>
                        <a {% if pagination.has_next %} href="{{ url_for('users.index') }}?page={{ pagination.next_num }}" {% endif %} aria-label="next">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                </ul>
            </nav>
        </div>
    {% endblock %}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95

    board.html

    {% extends 'base.html' %}
    {% block title %}
        文章详情
    {% endblock %}
    {% block styles %}
        {{ super() }}
    <style xmlns="http://www.w3.org/1999/html">
            #container{
                width: 1200px;
                margin: 0 auto;
            }
            #detail p{
                background-color: rgba(232,243,242,0.6);
                border-radius: 10px;
                margin-top: 20px;
                margin-bottom: 20px;
                padding: 20px 50px;
            }
            #detail h2{
                text-align: center;
            }
        style>
    {% endblock %}
    {% block newcontent %}
        <div id="container">
            <div id="detail">
                <div id="comment">
                    <div>
                        <form action="{{ url_for('users.show_board') }}" method="post">
                            <p>
                                用户留言:
                                <br>
                                <br>
                                <textarea name="board" placeholder="写下你的想说的,开始我们的对话" class="form-control" style="..." rows="5" cols="10">textarea>
                                <br>
                                <input type="submit" value="发表留言" class="btn btn-info">
                            p>
                        form>
    
                    div>
    
    
                    p>
                    <div id="comment_item">
                        {% if boardes %}
                            {% for board in boardes.item %}
                                <div class="item">
                                    <div id="item_left">
                                        <img src="{% if board.user.icon %}{{ url_for('static',filename=board.user.icon) }} {% else %}{{ url_for('static',filename='images/touxiang.jpg') }}{% endif %}" alt="">
                                    div>
                                    <div id="item_right">
                                        <p>
                                            <span>
                                                {% if not board.user_id %}
                                                    匿名用户
                                                {% else %}
                                                    {{ board.user.username }}
                                                {% endif %}
                                            span>
                                            <span>{{ board.mdatetime }}span>
                                        p>
                                        <p>{{ border.comment }}p>
                                    div>
                                div>
                            {% endfor %}
                        {% else %}
                            还没有任何的留言,赶快发表吧!
                        {% endif %}
    
    
                    div>
                    <div id="paginate">
                        <nav aria-label="...">
                            <ul class="pager">
                                <li class="previous {% if not boardes.has_prev %}disabled{% endif %}">
                                    <a {% if boardes.has_prev %} href="{{ url_for('users.show_board') }}?page={{ boardes.prev_num }}" {% endif %}><span aria-hidden="true">span> 上一页a>li>
    
                                <li class="next {% if not boardes.has_next %}disabled{% endif %}">
                                    <a {% if boardes.has_next %} href="{{ url_for('users.show_board') }}?page={{ boardes.next_num }}" {% endif %}>下一页 <span aria-hidden="true">span>a>li>
                            ul>
                        nav>
                    div>
                div>
            div>
        div>
    {% endblock %}
    
    {% block script %}
        {{ super() }}
        <script>
            $(function(){
                //文本域
                $('textarea[name="comment"]').focus(function(){
                    $(this).val("")
                })
            })
        script>
    {% endblock %}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    base.html

    {% extends "bootstrap/base.html" %}
    {% block title %}首页{% endblock %}
    {% block styles %}
        {{ super() }}
        <style>
            body{
                background-image: url("{{ url_for('static',filename='images/bg.jpg') }}");
                background-size: contain|cover;
                width: 100%;
                height: 100%;
            }
            body background-image{
    
            }
            #myfoot{
                border-top: 1px solid Black;
                font-size: 14px;
                text-align: center;
                color: Black;
            }
            .navbar{
            }
            .container {
                padding-right: 15px;
                padding-left: 15px;
                margin-right: auto;
                margin-left: auto;
            }
            .footer {
                padding: 30px 0;
                border-top: 1px solid #e5e5e5;
                margin-top: 70px;
            }
        style>
    {% endblock %}
    
    {% block navbar %}
        <nav class="navbar navbar-default ">
      <div class="container-fluid">
        
        <div class="navbar-header">
          <a class="navbar-brand" href="{{ url_for('users.index') }}">个人博客a>
        div>
    
        
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
          <ul class="nav navbar-nav">
              
            <li><a href="{{ url_for('users.show_about')}}">关于我a>li>
            <li class="dropdown">
              <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">文章类型 <span class="caret">span>a>
              <ul class="dropdown-menu">
                  {% for type in types %}
                    {% if not loop.last %}
                        <li><a href="{{ url_for('articles.type_search') }}?tid={{type.id}}">{{ type.type_name }}a>li>
                        <li role="separator" class="divider">li>
                    {% else %}
                        <li><a href="{{ url_for('articles.type_search') }}?tid={{type.id}}">{{ type.type_name }}a>li>
                    {% endif %}
                  {% endfor %}
              ul>
            li>
            <li><a href="{{ url_for('users.myphoto') }}">我的相册a>li>
            <li><a href="{{ url_for('users.show_board') }}">留言板a>li>
          ul>
          <form class="navbar-form navbar-left">
            <div class="form-group">
              <input type="text" class="form-control" placeholder="搜索">
            div>
            <button type="submit" class="btn btn-default">Submitbutton>
          form>
          <ul class="nav navbar-nav navbar-right">
              {% if user %}
                <li><img
                    src="{% if user.icon %} {{ url_for('static',filename=user.icon) }} {% else %} {{ url_for('static',filename='images/touxiang.png') }}{% endif %}"
                    alt="" style="border-radius:15px;margin-top: 8px;width: 30px;height: 30px">li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">欢迎!{{ user.username }} <span class="caret">span>a>
                    <ul class="dropdown-menu">
                        <li><a href="{{ url_for('users.center') }}">用户中心a>li>
                        <li><a href="{{ url_for('users.logout') }}">退出a>li>
                    ul>
                li>
              {% else %}
                <li><a href="{{url_for('users.login')}}">登录a>li>
                <li><a href="{{url_for('users.register')}}">注册a>li>
              {% endif %}
          ul>
        div>
      div>
    nav>
    {% endblock %}
    
    {% block content %}
        {% block newcontent %}
            <h1>Hello,Bootstraph1>
        {% endblock %}
    
        {% block footer %}
        <div class="container">
          <div class="col-md-6 col-sm-offset-2  col-lg-6">
            <div class="row about">
              <div class="col-sm-3">
                <h4>关于h4>
                <ul class="list-unstyled">
                  <li><a href="/about/">关于我们a>li>
                  <li><a href="/ad/">广告合作a>li>
                  <li><a href="/links/">友情链接a>li>
                  <li><a href="/hr/">招聘a>li>
                ul>
              div>
              <div class="col-sm-3">
                <h4>联系方式h4>
                <ul class="list-unstyled">
                  <li><a href="https://weibo.com/bootcss" title="Bootstrap中文网官方微博" target="_blank">新浪微博a>li>
                  <li><a href="mailto:admin@bootcss.com">电子邮件a>li>
                ul>
              div>
              <div class="col-sm-3">
                <h4>旗下网站h4>
                <ul class="list-unstyled">
                  <li><a href="https://www.bootcdn.cn/" target="_blank">BootCDNa>li>
                  <li><a href="https://pkg.phpcomposer.com/" target="_blank">Packagist中国镜像a>li>
                ul>
              div>
              <div class="col-sm-3">
                <h4>特别致谢h4>
                <ul class="list-unstyled">
                  <li><a href="https://www.maoyun.com/" target="_blank">猫云a>li>
    
                ul>
              div>
            div>
    
          div>
        div>
        <hr>
        <div class="row footer-bottom">
          <ul class="list-inline text-center">
            <li><a href="https://beian.miit.gov.cn/" target="_blank">京ICP备11008151号-6a>li><li>京公网安备11010802014853li>
          ul>
        div>
      div>
        {% endblock %}
    {% endblock %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146

    settings.py

    import os
    
    
    class Config:
        DEBUG = True
        SQLALCHEMY_DATABASE_URI = 'mysql://root:123456@127.0.0.1:3306/flaskblog'
        SQLALCHEMY_TRACK_MODIFICATIONS = True
        SQLALCHEMY_ECHO = True
        # secret_key加密码
        SECRET_KEY = 'JIAMIMA'
    
        RECAPTCHA_PUBLIC_KEY = "********"
        RECAPTCHA_PRIVATE_KEY = "***********"
        RECAPTCHA_PARAMETERS = {'hl':'zh','render':'explicit'}
        RECAPTCHA_DATA_ATTRS = {'theme':'dark'}
    
        # 项目路径
        BASE_DIR = os.path.dirname(os.path.abspath(__file__))
        # 静态文件夹的路径
        STATIC_DIR = os.path.join(BASE_DIR,'static')
        TEMPLATE_DIR = os.path.join(BASE_DIR,'templates')
        # 头像的上传目录
        UPLOAD_ICON_DIR = os.path.join(STATIC_DIR,'upload/icon')
        # 相册的上传目录
        UPLOAD_PHONE_DIR = os.path.join(STATIC_DIR,'upload/phone')
    
    
    class DevelopmentConfig(Config):
        ENV = 'development'
        DEBUG = True
    
    class ProductionConfig(Config):
        ENV = 'production'
        DEBUG = True
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    app.py

    from flask_migrate import Migrate, MigrateCommand
    from flask_script import Manager
    from flask_wtf import CSRFProtect
    
    from apps.user.models import *
    from apps.article.models import *
    from apps.goods.models import *
    
    from apps import create_app
    from exts import db
    
    app = create_app()
    manager = Manager(app = app)
    
    migrate = Migrate(app = app, db = db)
    manager.add_command('db',MigrateCommand)
    
    # csrf = CSRFProtect(app=app)
    
    
    @manager.command
    def init():
        print('初始化')
    
    if __name__ == '__main__':
        manager.run()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    apps下的init.py

    from flask import Flask
    
    import settings
    from apps.article.view import article_bp
    from apps.article.views import articles_bp
    from apps.goods.view import goods_bp
    from apps.user.view import user_bp
    from apps.user.views import users_bp
    from exts import db, bootstrap, cache
    
    config = {
        'CACH_TYPE': 'REDIS',
        'CACHE_REDIS_HOST': '127.0.0.1',
        'CACHE_REDIS_PORT': 6379
        # 'CACHE_REDIS_PASSWORD':'',
        # 'CACHE_REDIS_DB':''
    }
    
    
    def create_app():
        app = Flask(__name__,template_folder='../templates',static_folder='../static')
        app.config.from_object(settings.DevelopmentConfig)
        # 初始化db
        db.init_app(app)
        bootstrap.init_app(app)
        cache.init_app(app = app,config = config)
        # app.register_blueprint(user_bp)
        app.register_blueprint(users_bp)
        app.register_blueprint(article_bp)
        app.register_blueprint(articles_bp)
        app.register_blueprint(goods_bp)
    
        return app
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    运行结果:

    在这里插入图片描述

  • 相关阅读:
    GET请求和POST请求区别
    Maven配置代理
    2022中国机器人产业报告发布 企业如何应对新阶段下的增长与竞争?
    分销会员系统开发
    Linux多线程环境下信号处理机制
    js点击按钮切换图片
    Google浏览器和IE浏览器配置User-Agent方法
    Day130.MySQL高级:Liunx安装、三大范式、InnoDB、数据结构、B+树
    VictoriaLogs 要凭什么革了各家日志存储的命
    5. 吴恩达深度学习--搭建卷积神经网络模型以及应用
  • 原文地址:https://blog.csdn.net/weixin_42724501/article/details/126350684