- 图片验证码
uuid:前端js生成,时间戳+机器码+随机数,(image_code_id)
图片验证码:captcha生成,→name,text,image
在redis中保存图片验证码文本,(uuid,过期时间,text)
向前端返回图片验证码的图片,response = make_response(image)
- 发送短信
从redis获取真实验证码,读完之后删除,
先比较图片验证码:real_image_code.lower() != image_code.lower():
通过手机号查询数据库,看是否已注册
生成短信验证码:sms_code = '%06d' % random.randint(0, 999999)
保存短信验证码:手机号,过期时间,验证码
调用云通讯发送
- 注册
检查用户是否已注册
user = User.query.filter(User.mobile == mobile).first()
提交用户数据到数据库
db.session.add(user)
db.session.commit()
db.session.rollback()
缓存用户数据到redis中:
请求上下文中有request和session两个对象,一个负责处理http请求内容,一个负责处理用户信息。
判断用户名和密码正确(一起判断,避免反向解析)
if user is None or not user.check_password(password):
g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别
- 个人中心
获取图片
avatar = request.files.get('avatar')
读取成二进制
image_data = avatar.read()
利用第三方上传图片
给我们返回一个图片名
我们需要拼接上云空间的链接+图片名,返回给前端
- 发布新闻
查询所有分类,放到一个列表中,移除最新分类,category_list.pop(0)
通过request获取表单和文件数据
检查参数完整性
然后需要将获取的图片读取成二进制形式
调用第三方工具上传图片
闻图片对新闻来说是一个整体,也要一起存储到mysql中,
- 用户登录后首页的展示
这里主要是数据库的查询,然后组装给模板的数据,(字典格式)
return render_template('news/index.html',data=data)
- 加载logo图标
# 加载logo图标,浏览器默认请求跟路径下
@news_blue.route('/favicon.ico')
def favicon():
# 发送文件给浏览器
return current_app.send_static_file('static/favicon.ico')
- 点击分类时的展示逻辑
# 判断新闻分类,*filters是拆包,如果前端点击的是1(cid=1)分类,列表为空,查所有;如果大于1,则查询cid对应的分类(通过模型类)
filters = []
if cid >1:
filters.append(News.category_id == cid)
try:
paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page,per_page,False)
组装字典,向前端返回数据
- 点击排行的展示
查询数据库通过点击量排序,获取指定条数据
news_list = News.query.order_by(News.clicks.desc()).limit(6)
整理成前端需要的格式
news_click_list = []
for news in news_list:
news_click_list.append(news.to_dict())
- 小点,点击过新闻后,点击次数加1
新闻详情:news = News.query.get(news_id)
新闻点击次数加1:news.clicks += 1
记得要提交到数据库
- 收藏功能
首先要判断用户是否登录:user = g.user
需要检查参数:新闻id和收藏状态action
注意:一条新闻不能被收藏两次
- 后台界面
# 点击了收藏
if action == 'collect':
# 判断用户是否收藏过(一条新闻不能被收藏两次)
if news not in user.collection_news:
user.collection_news.append(news)
else:
user.collection_news.remove(news)
- 权限控制
避免普通用户登录到后台界面,使用请求钩子在每次访问前进行判断,判断是否请求登录页面,是否有用户登录,是否是管理员,条件不满足直接重定向到主页
@admin_blu.before_request
def before_request():
# 判断如果不是登录页面的请求
if not request.url.endswith(url_for("admin.admin_login")):
user_id = session.get("user_id")
is_admin = session.get("is_admin", False)
if not user_id or not is_admin:
# 判断当前是否有用户登录,或者是否是管理员,如果不是,直接重定向到项目主页
return redirect('/')
- 退出后要清除session中管理员数据
session.pop('user_id', None)
session.pop('nick_name', None)
session.pop('mobile', None)
session.pop('is_admin', None)
- 注意
界面提示 The CSRF token is missing
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
- 查询总人数
除去管理员
total_count = User.query.filter(User.is_admin == False).count()
- 查询月新增人数
mon_count = 0
try:
now = time.localtime()
mon_begin = '%d-%02d-01' % (now.tm_year, now.tm_mon)
mon_begin_date = datetime.strptime(mon_begin, '%Y-%m-%d')
mon_count = User.query.filter(User.is_admin == False, User.create_time >= mon_begin_date).count()
except Exception as e:
current_app.logger.error(e)
- 查询日新增人数
day_count = 0
try:
day_begin = '%d-%02d-%02d' % (now.tm_year, now.tm_mon, now.tm_mday)
day_begin_date = datetime.strptime(day_begin, '%Y-%m-%d')
day_count = User.query.filter(User.is_admin == False, User.create_time > day_begin_date).count()
except Exception as e:
current_app.logger.error(e)
- 获取每天活跃人数
# 获取到当天00:00:00时间
now_date = datetime.strptime(datetime.now().strftime('%Y-%m-%d'), '%Y-%m-%d')
# 定义空数组,保存数据
active_date = []
active_count = []
# 依次添加数据,再反转
for i in range(0, 31):
begin_date = now_date - timedelta(days=i)
end_date = now_date - timedelta(days=(i - 1))
active_date.append(begin_date.strftime('%Y-%m-%d'))
count = 0
try:
count = User.query.filter(User.is_admin == False, User.last_login >= day_begin,
User.last_login < day_end).count()
except Exception as e:
current_app.logger.error(e)
active_count.append(count)
active_date.reverse()
active_count.reverse()
data = {"total_count": total_count, "mon_count": mon_count, "day_count": day_count, "active_date": active_date,
"active_count": active_count}
- 按用户登录时间倒序展示用户列表
paginate = User.query.filter(User.is_admin == False).order_by(User.last_login.desc()).paginate(page, constants.ADMIN_USER_PAGE_MAX_COUNT, False)
users = paginate.items
current_page = paginate.page
total_page = paginate.pages
将模型列表转成字典
users_list = []
for user in users:
users_list.append(user.to_admin_dict())
context = {"total_page": total_page, "current_page": current_page, "users": users_list}
return render_template('admin/user_list.html',data=context)