django中使用redis做缓存中间件
程序员文章站
2024-03-15 19:59:06
...
由于电商后台的首页,客户要求的数据特别多,都是从各个表中查出来的,我大致算了一下,大概要查30多个表,我想这不行啊,于是决定使用使用redis作为缓存使用
-
客户要求的首页展示数据,这只是一小小部分
-
我决定写一个脚本,每天晚上凌晨时查询db,放入redis,
# -*- coding: utf-8 -*-
#!/usr/bin/python3
import os
import sys
import datetime
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path.append(os.path.join(BASE_DIR,'one_fashion'))
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_fashion.settings.settings")
import django
django.setup()
import datetime
import logging
from django_redis import get_redis_connection
from users.models import User, UserInfo, VIPInfo
from orders.models import OrderInfo
from payment.models import Recharge
from management.utils import Public_func
from message.models import Message
from django.db.models import Q, Count, F, Case, When, Value
logger = logging.getLogger('django')
if __name__ == "__main__":
"""每日凌晨执行定时任务,存入缓存"""
now_time = datetime.datetime.now()
time = now_time - datetime.timedelta(days=1)
# 网站概览/用户
accumulated = User.objects.filter(is_staff=False).count() # 累计用户
yesterday_increased = User.objects.filter(date_joined__range=(time, now_time)).count() # 昨日新增数
# 昨日付费人数(下单用户和开vip用户)
pay_user_ord = OrderInfo.objects.filter(create_time__range=(time, now_time), status=2).count()
pay_user_vip = VIPInfo.objects.filter(create_time__range=(time, now_time)).count()
pay_user_count = pay_user_ord + pay_user_vip
# todo 昨日活跃数(登录人数 User表中的last_login)
login_count = User.objects.filter(last_login__range=(time, now_time)).count()
# 网站概览/付费收入
# 昨天收入
before_conclude_actual_amount = 0
ord_query = OrderInfo.objects.filter(create_time__range=(time, now_time), status=2) # 订单收入
for ord_obj in ord_query:
before_conclude_actual_amount += int(ord_obj.actual_amount)
vip_list = VIPInfo.objects.filter(create_time__range=(time, now_time)).values_list('level', flat=True) # vip收入
for level in vip_list:
rec_obj = Recharge.objects.filter(level=level).first()
before_conclude_actual_amount += int(rec_obj.price)
# 本月收入
first_day = Public_func().month_first_day(now_time) # 返回当月的第一天的零点零分
month_conclude_actual_amount = 0
ord_query = OrderInfo.objects.filter(create_time__range=(first_day, now_time), status=2) # 订单收入
for ord_obj in ord_query:
month_conclude_actual_amount += int(ord_obj.actual_amount)
vip_list = VIPInfo.objects.filter(create_time__range=(first_day, now_time)).values_list('level', flat=True) # vip收入
for level in vip_list:
rec_obj = Recharge.objects.filter(level=level).first()
month_conclude_actual_amount += int(rec_obj.price)
# 存入缓存
try:
conn = get_redis_connection('admin_home')
pl = conn.pipeline(True)
pl.multi()
pl.hmset('user', {'accumulated': accumulated, 'yesterday_increased': yesterday_increased, 'pay_user_count':pay_user_count, 'login_count':login_count})
pl.hmset('pay', {'before_conclude_actual_amount': before_conclude_actual_amount, 'month_conclude_actual_amount': month_conclude_actual_amount,})
pl.execute()
except Exception as e:
logger.error(e)
- 由于查询数据较为固定,所以我没有考虑db和redis数据不一致,因为这个场景根本不需要,接口代码
import datetime
import logging
from django_redis import get_redis_connection
from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView, GenericAPIView
from rest_framework.permissions import IsAuthenticated
from one_fashion.utils.permissions import AdminUserPermission
from one_fashion.utils.api_response import APIResponse
from management.utils import Public_func
from users.models import User, UserInfo, VIPInfo
from django.db.models import Q, Count, F, Case, When, Value
from message.models import Message
logger = logging.getLogger('django')
class WebsiteOverviewView(GenericAPIView):
"""首页网站概览模块"""
permission_classes = [IsAuthenticated, AdminUserPermission]
def get(self, request, *args, **kwargs):
try:
conn = get_redis_connection('admin_home')
pl = conn.pipeline(True)
pl.watch('user')
pl.multi()
pl.hgetall('user')
user_dict = pl.execute()[0]
pl.unwatch()
# 如果事务没有执行
if not user_dict:
return APIResponse.fail(message='获取数据失败,请刷新重试')
data = {'data':user_dict}
except Exception as e:
logger.error(e)
return APIResponse.fail(message='服务器错误,请刷新重试')
return APIResponse.success(data=data)
- 由于代码内容没有写完,所以接口代码应该还有一段就是如果redis数据不存在,那么应该再查询db返回数据的,不能导致如果redis出现状况,数据不存在,给前端返回的数据为空
- settin代码:
# 用来缓存后台首页数据
"admin_home": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/6",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 20, "decode_responses": True}
}
},
- 接口返回数据:
{
"data": {
"data": {
"accumulated": "43",
"yesterday_increased": "0",
"pay_user_count": "1",
"login_count": "0"
}
},
"code": 0,
"message": ""
}
推荐阅读