django中使用redis做缓存中间件

47 篇文章 0 订阅

由于电商后台的首页,客户要求的数据特别多,都是从各个表中查出来的,我大致算了一下,大概要查30多个表,我想这不行啊,于是决定使用使用redis作为缓存使用

  1. 客户要求的首页展示数据,这只是一小小部分
    在这里插入图片描述

  2. 我决定写一个脚本,每天晚上凌晨时查询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)
  1. 由于查询数据较为固定,所以我没有考虑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)
  1. 由于代码内容没有写完,所以接口代码应该还有一段就是如果redis数据不存在,那么应该再查询db返回数据的,不能导致如果redis出现状况,数据不存在,给前端返回的数据为空
  2. 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}
                }
            },
  1. 接口返回数据:
{
    "data": {
        "data": {
            "accumulated": "43",
            "yesterday_increased": "0",
            "pay_user_count": "1",
            "login_count": "0"
        }
    },
    "code": 0,
    "message": ""
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值