1.项目介绍
类型:是一个新闻类型的网站
前后端不分离:耦合度高,如果客户端换成app,那么页面效果会出问题.
技术实现:python3.x+Flask+第三方sdk(云通讯+七牛云)+部署(阿里云)
数据存储:redis + mysql
第三方扩展:七牛云和云通信
部署:基于Ubuntu16.04
在使用pycharm的时候有一个小技巧(快速定位到文件地址):
2.配置文件抽取
目的:方便今后做扩展,维护,管理更加高效
操作流程:
1/定义了config
文件
2/将config
配置类抽取到config文件中
3/提供了3中环境下的配置信息
4/提供了一个config_dict
的统一访问入口的字典
config.py
1import logging
2from datetime import timedelta
3from redis import StrictRedis
4
5#设置配置信息(基类配置信息)
6class Config(object):
7 #调试信息
8 DEBUG = True
9 SECRET_KEY = "fdfdjfkdjfkdf"
10
11 #数据库配置信息
12 SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:123456@localhost:3306/info36"
13 SQLALCHEMY_TRACK_MODIFICATIONS = False
14
15 #redis配置信息
16 REDIS_HOST = "127.0.0.1"
17 REDIS_PORT = 6379
18
19 #session配置信息
20 SESSION_TYPE = "redis" #设置session存储类型
21 SESSION_REDIS = StrictRedis(host=REDIS_HOST,port=REDIS_PORT) #指定session存储的redis服务器
22 SESSION_USE_SIGNER = True #设置签名存储
23 PERMANENT_SESSION_LIFETIME = timedelta(days=2) #设置session有效期,两天时间
24
25 #默认日志级别
26 LEVEL_NAME = logging.DEBUG
27
28#开发环境配置信息
29class DevelopConfig(Config):
30 pass
31
32
33#生产(线上)环境配置信息
34class ProductConfig(Config):
35 DEBUG = False
36 LEVEL_NAME = logging.ERROR
37
38
39#测试环境配置信息
40class TestConfig(Config):
41 pass
42
43
44#提供一个统一的访问入口
45config_dict = {
46 "develop":DevelopConfig,
47 "product":ProductConfig,
48 "test":TestConfig
49}
3.初始化信息抽取
目的:将初始化信息抽取到单独的文件,方便做统一的管理
操作流程:
1/将manager
中的初始化信息抽取到info的init
文件中
2/定义了create_app
方法接收了一个config_name
参数
3/根据config_name
加载不同的环境下的配置类信息
4/再返回一个完整的app给manager
文件
info包下的__init__.py
1import logging
2from logging.handlers import RotatingFileHandler
3
4from flask import Flask
5from flask_sqlalchemy import SQLAlchemy
6from redis import StrictRedis
7from flask_session import Session
8from flask_wtf.csrf import CSRFProtect
9from config import config_dict
10
11#定义redis_store变量
12redis_store = None
13
14#定义工厂方法
15def create_app(config_name):
16 app = Flask(__name__)
17
18 #根据传入的配置类名称,取出对应的配置类
19 config = config_dict.get(config_name)
20
21 #调用日志方法,记录程序运行信息
22 log_file(config.LEVEL_NAME)
23
24 #加载配置类
25 app.config.from_object(config)
26
27 #创建SQLAlchemy对象,关联app
28 db = SQLAlchemy(app)
29
30 #创建redis对象
31 global redis_store #global将局部变量声明为一个全局的
32 redis_store = StrictRedis(host=config.REDIS_HOST,port=config.REDIS_PORT,decode_responses=True)
33
34 #创建Session对象,读取APP中session配置信息
35 Session(app)
36
37 #使用CSRFProtect保护app
38 CSRFProtect(app)
39
40 #将首页蓝图index_blue,注册到app中
41 from info.modules.index import index_blue
42 app.register_blueprint(index_blue)
43
44 return app
45
46def log_file(LEVEL_NAME):
47 # 设置日志的记录等级,常见的有四种,大小关系如下: DEBUG < INFO < WARNING < ERROR
48 logging.basicConfig(level=LEVEL_NAME) # 调试debug级,一旦设置级别那么大于等于该级别的信息全部都会输出
49 # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
50 file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 100, backupCount=10)
51 # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
52 formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
53 # 为刚创建的日志记录器设置日志记录格式
54 file_log_handler.setFormatter(formatter)
55 # 为全局的日志工具对象(flask app使用的)添加日志记录器
56 logging.getLogger().addHandler(file_log_handler)
4.视图函数抽取
目的:视图函数是用来处理对应业务的,可能有很多,应该使用蓝图进行统一的管理
操作流程:
1/创建了modules
模块,用来管理所有的蓝图
2/再modules
底下创建了index
包
3/在index
中创建了index_blue
蓝图,创建了views
文件,并使用index_blue
装饰视图函数
4/在create_app
方法内部注册index_blue
到app中
modules下的index下的__inint__.py
1from flask import Blueprint
2
3#1.创建蓝图对象
4index_blue = Blueprint("index",__name__)
5
6#2.导入views文件装饰视图函数
7# from info.modules.index import views
8from . import views
modules下的index下的views.py
1from info import redis_store
2from . import index_blue
3import logging
4from flask import current_app
5
6@index_blue.route('/',methods=["GET","POST"])
7def hello_world():
8
9 #测试redis存取数据
10 # redis_store.set("name","laowang")
11 # print(redis_store.get("name"))
12
13 #测试session存取
14 # session["name"] = "zhangsan"
15 # print(session.get("name"))
16
17 #没有继承日志之前,使用print输出,不方便做控制
18 # print("helloworld")
19
20 #使用日志记录方法loggin进行输出可控
21 logging.debug("输入调试信息")
22 logging.info("输入详细信息")
23 logging.warning("输入警告信息")
24 logging.error("输入错误信息")
25
26 #也可以使用current_app来输出日志信息,输出的时候有分割线,写在文件中完全一样
27 # current_app.logger.debug("输入调试信息2")
28 # current_app.logger.info("输入详细信息2")
29 # current_app.logger.warning("输入警告信息2")
30 # current_app.logger.error("输入错误信息2")
31
32
33 return "helloworld"
在上面的代码中有可能logging和current_app两个方法导出日志信息的时候,大家不知道其中的一个区别,那么下面用图片给大家演示一下:
上面的图片是在pycharm中的控制台显示效果,当然我们也可以将其输出到日志文件中,他们的区别就是在控制台显示的时候,current_app输出更加的美观,便于查看;但是在日志中,两种方法的效果是完全一样的,没有任何不同
5.循环导包
解决办法:在控制台中,查看到底是哪些文件之间产生了循环导包,依次点开所有的文件,只需要想办法断掉其中一环即可
ImportError: cannot import name 'redis_store'
循环导包错误
6.redis存储设置
问题:
1/redis_store
创建再了create_app
方法内部,外界不能导入使用
2/在create_app
方法外部创建一个空的redis_store
使用global装饰方法内部的redis_store
即可
7.日志信息集成
目的:
1/记录用户的行为
2/记录分析软件的问题
3/便于给产品经理提供设计依据
日志最大的限制,够了之后会再生成一个log文件,最多10个日志,编号是10,有个没有编号的,其实是11个.如果文件不够用了,会将最开始的文件给删除,最后建一个文件,然后将所有日志文件编号从新排一下
操作流程:
1/定义好log_file
方法,拷贝日志记录方法进来
2/在create_app
方法中调用即可
1import logging
2from logging.handlers import RotatingFileHandler
3def log_file(LEVEL_NAME):
4 # 设置日志的记录等级,常见的有四种,大小关系如下: DEBUG < INFO < WARNING < ERROR
5 logging.basicConfig(level=LEVEL_NAME) # 调试debug级,一旦设置级别那么大于等于该级别的信息全部都会输出
6 # 创建日志记录器,指明日志保存的路径、每个日志文件的最大大小、保存的日志文件个数上限
7 file_log_handler = RotatingFileHandler("logs/log", maxBytes=1024 * 1024 * 100, backupCount=10)
8 # 创建日志记录的格式 日志等级 输入日志信息的文件名 行数 日志信息
9 formatter = logging.Formatter('%(levelname)s %(filename)s:%(lineno)d %(message)s')
10 # 为刚创建的日志记录器设置日志记录格式
11 file_log_handler.setFormatter(formatter)
12 # 为全局的日志工具对象(flask app使用的)添加日志记录器
13 logging.getLogger().addHandler(file_log_handler)
8.日志配置抽取
目的:为了便于去管理不同环境下的日志级别
操作流程:
1/在config
配置文件中,给DevelopConfig和ProductConfig
设置不同的级别
2/在调用create_app
方法的时候,传递对应环境的key值
3/取出对应的环境下的日志级别,将日志级别传递到log_file
方法中
当前的一个目录结构:
1from config import config_dict
2#定义工厂方法
3def create_app(config_name):
4 app = Flask(__name__)
5
6 #根据传入的配置类名称,取出对应的配置类
7 config = config_dict.get(config_name)
8
9 #调用日志方法,记录程序运行信息
10 log_file(config.LEVEL_NAME)
config配置文件
1import logging
2
3#设置配置信息(基类配置信息)
4class Config(object):
5 ....
6 #默认日志级别
7 LEVEL_NAME = logging.DEBUG
8#开发环境配置信息
9class DevelopConfig(Config):
10 pass
11
12#生产(线上)环境配置信息
13class ProductConfig(Config):
14 DEBUG = False
15 LEVEL_NAME = logging.ERROR
1import logging
2from logging.handlers import RotatingFileHandler
3def log_file(LEVEL_NAME):
4 # 设置日志的记录等级,常见的有四种,大小关系如下: DEBUG < INFO < WARNING < ERROR
5 logging.basicConfig(level=LEVEL_NAME) # 调试debug级,一旦设置级别那么大于等于该级别的信息全部都会输出
下面将上面的过程用图片进行一个演示
9.gitkeep忽略日志文件
目的:可以让logs
空文件夹能够被提交到git仓库
创建方法:直接在logs文件夹下建立一个空的文件名字为.gitkeep
10.表结构分析
目的:主要是了解xx网站中的主要的7张表之间的关系
注意点:看keynote的图
11.数据库迁移
目的:将模型类迁移成数据库的具体表
操作流程:
1/导入models,constants文件到info中
2/将create_app中的SQLAlchemy(app),改成两句话
1/db= Sqlalchemy(),定义在create_app外部
2/db.init_app(app),定义在create_app内部
3/在manager.py文件中进行迁移
1/导入Manager,Migrate,MigrateCommand
2/创建manager对象管理app
3/使用Migrate,挂链app,db
4/给manager添加一条操作命令
5/执行迁移(init,Migrate,upgrade)
12.静态文件集成
目的:为了给用户提供访问页面
操作流程:将status文件夹添加到info里面,然后使用Git管理起来
13.首页显示
目的:在用户访问首页的时候可以给用户
操作步骤:
1/先在info中创建一个template文件夹
2/将status/news中的 index.html拖入到templates/news文件夹中
3/再访问根路径的时候,使用render_template将index.html渲染出来
14.网站logo显示
目的:显示网站的标识,显示在title中
注意点:
1/当浏览器访问每个网站的时候都会自动去请求一个/favicon.ico的接口
2/我们只需要在程序中,写上/favicon.ico的接口,然后返回一张图片即可
3/在flask中需要使用一个方法current_app.send_static_file("文件名")
1/send_static_file("文件1"),该方法会自动去static静态文件夹中寻找文件1
15.图片验证码分析
目的:为了保证注册,登录的用户是个真实的用户在操作,为了去获取短信验证码
注意点:
1/在服务器内部保存图片验证码的时候,前端需要带一个随机字符串(uuid)过来
2/uuid作为key,图片验证码的值作为value存储
16.图片验证码集成
目的:便于程序调用,生成图片验证码
操作流程:
1/在info中创建utils包,将captch导入即可
17.图片验证码视图函数
目的:为了方便前端调用,获取图片验证码
18.图片验证码去重完善
目的: 不能在服务端存储多份图片,容易导致后端的服务器内存不足
操作流程
1/获取参数,cur_id,pre_id
2/调用generator_captch()生成图片验证码
3/存储图片验证码到redis
4/判断是否有上一次图片验证码,如果有则删除
5/返回一张图片,并指定图片格式
优质文章推荐: