flask的简单使用

魏康安
2023-12-01

一、初始化flask实例
在项目路径下,建立一个用于初始化app的实例对象的app.py文件和一个用于项目启动的文件(一般与项目同名)的py文件,这里使用manage.py作为示例。

# vi app.py
from flask import Flask

from configs import Config
def create_app(config):
    app = Flask(__name__,static_folder=Config.STATIC_FOLDER, template_folder=Config.TEMPLATES_FOLDER)
    # 加载配置文件
    app.config.from_object(config)
    return app
# vi manage.py
from flask_script import Manager
from app import create_app
from configs import DevConfig
from models import db
from flask_migrate import Migrate, MigrateCommand

# 初始化flask实例并加载配置文件
app = create_app(DevConfig)
# 为app对象添加扩展命令
manager = Manager(app)

# 完成连接数据库的初始化
db.init_app(app)
Migrate(app, db)
# 添加扩展的数据库迁移命令
manager.add_command("db", MigrateCommand)

if __name__ == '__main__':
    manager.run()
# 配置文件如下:
class Config(object):
    Debug = False
    # 模板目录
    TEMPLATES_FOLDER = os.path.join(BASE_DIR, "templates")
    # 静态文件目录
    STATIC_FOLDER = os.path.join(BASE_DIR, "static")
    SQLALCHEMY_DATABASE_URI = 'mysql://root:123456@host:3310/xjzx10'
    SQLALCHEMY_TRACK_MODIFICATIONS = True
class DevConfig(Config):
    Debug = True
class UatConfig(Config):
    Debug = True
class ProConfig(Config):
    Debug = False

启动命令:python manage runserver -h 0.0.0.0 -p 5000
二、路由蓝图
在项目目录下,新建一个用于注册user的视图路由的user_views.py文件,内容如下:

from flask import Blueprint, render_template
user_blueprint = Blueprint('user', __name__, url_prefix="user")

# 注册路由
@news_blueprint.route('/')
def index():
    return render_template('index.html')

在项目目录下,新建一个用于注册admin的视图路由的admin_views.py文件,内容如下:

from flask import Blueprint
admin_blueprint = Blueprint('admin', __name__, url_prefix="/admin")

在app.py文件中注册蓝图:

from flask import Flask
from user_views import user_blueprint
from admin_views import admin_blueprint

def create_app(config):
    app = Flask(__name__)
    app.config.from_object(config)
    app.register_blueprint(user_blueprint)
    app.register_blueprint(admin_blueprint)
    return app

三、建立模型
在项目目录下,创建一个model.py的文件,内容如下:

import pymysql
from datetime import datetime
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash

pymysql.install_as_MySQLdb()

db = SQLAlchemy()

class BaseModel(object):
    create_time = db.Column(db.DateTime, default=datetime.now())
    update_time = db.Column(db.DateTime, default=datetime.now())
    isDelete = db.Column(db.Boolean, default=False)


tb_news_collect = db.Table(
    'tb_news_collect',
    db.Column('user_id', db.Integer, db.ForeignKey('user_info.id'), primary_key=True),
    db.Column('news_id', db.Integer, db.ForeignKey('news_info.id'), primary_key=True)
)
tb_user_follow = db.Table(
    'tb_user_follow',
    db.Column('origin_user_id', db.Integer, db.ForeignKey('user_info.id'), primary_key=True),
    db.Column('follow_user_id', db.Integer, db.ForeignKey('user_info.id'), primary_key=True)
)


class NewsCategory(db.Model, BaseModel):
    __tablename__ = 'news_category'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(10))
    #关系属性:不会在表中生成字段
    #lazy='dynamic'惰性加载category.news
    #category=NewsCategory.query.get(1)
    #当使用lazy='dynamic'时不会查询分类的新闻信息
    #这样设置的好处:可能本次只是使用分类对象,不想使用新闻对象,则可以减少数据库的查询量
    news = db.relationship('NewsInfo', backref='category', lazy='dynamic')


class NewsInfo(db.Model, BaseModel):
    __tablename__ = 'news_info'
    id = db.Column(db.Integer, primary_key=True)
    category_id = db.Column(db.Integer, db.ForeignKey('news_category.id'))
    pic = db.Column(db.String(50))
    title = db.Column(db.String(30))
    summary = db.Column(db.String(200))
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey('user_info.id'))
    click_count = db.Column(db.Integer, default=0)
    comment_count = db.Column(db.Integer, default=0)
    status = db.Column(db.SmallInteger, default=1)
    reason=db.Column(db.String(100),default='')
    comments = db.relationship('NewsComment', backref='news', lazy='dynamic', order_by='NewsComment.id.desc()')

    # @property
    # def pic_url(self):
    #     return current_app.config.get('QINIU_URL') + self.pic
    #
    # def to_index_dict(self):
    #     return {
    #         'id': self.id,
    #         'pic_url': self.pic_url,
    #         'title': self.title,
    #         'summary': self.summary,
    #         'author': self.user.nick_name,
    #         'author_avatar': self.user.avatar_url,
    #         'author_id': self.user_id,
    #         'udpate_time': self.update_time.strftime('%Y-%m-%d')
    #     }


class UserInfo(db.Model,BaseModel):
    __tablename__ = 'user_info'
    id = db.Column(db.Integer, primary_key=True)
    avatar = db.Column(db.String(50), default='user_pic.png')
    nick_name = db.Column(db.String(20))
    signature = db.Column(db.String(200))
    public_count = db.Column(db.Integer, default=0)
    follow_count = db.Column(db.Integer, default=0)
    mobile = db.Column(db.String(11))
    password_hash = db.Column(db.String(200))
    gender = db.Column(db.Boolean, default=False)
    isAdmin = db.Column(db.Boolean, default=False)
    #用户对新闻为1:多,所以将新闻关联属性定义在User类中
    news = db.relationship('NewsInfo', backref='user', lazy='dynamic')
    #用户对评论为1:多,所以将评论关联属性定义在User类中
    comments = db.relationship('NewsComment', backref='user', lazy='dynamic')
    #用户对收藏新闻为多:多,此时关系属性可以定义在任意类中,当前写在了User类中
    news_collect = db.relationship(
        'NewsInfo',
        #多对多时,指定关系表,因为外键存储在这个关系表中
        secondary=tb_news_collect,
        lazy='dynamic'
        #此处没有定义backref,作用是根据新闻找用户,因为不需要使用这个功能,所以可以不定义
    )
    #用户关注用户为自关联多对多,关系属性只能定义在User类中
    #使用user.follow_user可以获得当前user用户关注的用户列表
    #select * from users inner join tb_user_follow on user.id=origin_user_id
    follow_user = db.relationship(
        'UserInfo',
        #多对多,所以指定关系表
        secondary=tb_user_follow,
        lazy='dynamic',
        #user.follow_by_user可以获得当前user用户的粉丝用户列表
        backref=db.backref('follow_by_user', lazy='dynamic'),
        #在使用user.follow_user时,user.id与关系表中哪个字段判等
        primaryjoin=id == tb_user_follow.c.origin_user_id,
        #在使用user.follow_by_user时,user.id与关系表中的哪个字段判等
        secondaryjoin=id == tb_user_follow.c.follow_user_id
    )

    @property
    def password(self):
        pass

    @password.setter
    def password(self, pwd):
        self.password_hash = generate_password_hash(pwd)

    def check_pwd(self, pwd):
        return check_password_hash(self.password_hash, pwd)

    # @property
    # def avatar_url(self):
    #     return current_app.config.get('QINIU_URL') + self.avatar

class NewsComment(db.Model, BaseModel):
    __tablename__ = 'news_comment'
    id = db.Column(db.Integer, primary_key=True)
    news_id = db.Column(db.Integer, db.ForeignKey('news_info.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user_info.id'))
    like_count = db.Column(db.Integer, default=0)
    comment_id = db.Column(db.Integer, db.ForeignKey('news_comment.id'))
    msg = db.Column(db.String(200))
    comments = db.relationship('NewsComment', lazy='dynamic')

迁移命令:

python '文件名' db init 创建迁移仓库 
python '文件名' db migrate -m '版本号' 创建自动迁移脚本 
python '文件名' db upgrade  更新数据库 
python '文件名' db history 查看历史版本 
python '文件名' db downgrade '版本号'(系统定义的版本号)  回退数据库  

四、日记
在项目目录下,创建一个logs的目录,然后在其子目录下创建想要的配置的日记文件,如connect或error等等;在项目目录下,创建一个log.py文件,内容如下:

import logging
from logging.handlers import RotatingFileHandler

class Logger(object):
	def __innit__(self):
		# logging初始化工作
		logging.basicConfig()
		# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
		connect_file_log_handler = RotatingFileHandler(config.BASE_DIR + "/logs/connect.log", maxBytes=1024 * 1024 * 100,backupCount=10)
		# 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
		formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
		# 为刚创建的日志记录器设置日志记录格式
		connect_file_log_handler.setFormatter(formatter)
		# connect的初始化工作
		self.logger_connect = logging.getLogger("connect")
		# 设置connect的日记等级
		self.logger_connect.setLevel(logging.INFO)
		self.logger_connect.addHandler(connect_file_log_handler)
		
		# 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
		error_file_log_handler = RotatingFileHandler(config.BASE_DIR + "/logs/error.log", maxBytes=1024 * 1024 * 100,backupCount=10)
		# 为刚创建的日志记录器设置日志记录格式
		error_file_log_handler.setFormatter(formatter)
		# error的初始化工作
		self.logger_error = logging.getLogger("error")
		# 设置connect的日记等级
		self.logger_error.setLevel(logging.error)
		self.logger_error.addHandler(error_file_log_handler)
	def connect(self,msg):
		self.logger_connect.info(msg)
	def error(self,msg):
		self.logger_error.info(msg)
logger = Logger()

可以将日记对象初始化到app的实例中,然后使用flask中的上下文管理对象current_app调用更为方便:

# vi app.py
from flask import Flask
from user_views import user_blueprint
from admin_views import admin_blueprint

from log import logger
def create_app(config):
    app = Flask(__name__)
    app.config.from_object(config)
    app.register_blueprint(user_blueprint)
    app.register_blueprint(admin_blueprint)
    app.connect = logger.connect
     app.error = logger.error
    return app
 类似资料: