路飞-轮播图功能-缓存定时任务

路飞-后端首页轮播图接口

轮播图属于首页功能,后端在apps内创建home 在homeapp中创建banner表
由于很多表有公共的字段,那我们就可以把公共的字段创建一个类 然后用表继承
这样所有的表都有公共字段了

1.在utils下新建 common_model.py 文件中编写公共字段类

from django.db import models


# Create your models here.

class BaseClass(models.Model):
    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    is_show = models.BooleanField(default=True, verbose_name='是否展示')
    orders = models.IntegerField(verbose_name='优先级')

    class Meta:
        abstract = True
        # 该字段意思 虚拟表,不需要在数据库创建 只用来继承

2.在models中编写banner表

from LufeiApi.utils.common_models import BaseClass
from django.db import models


class Banner(BaseClass):
    title = models.CharField(max_length=32, verbose_name='广告名称')
    image = models.ImageField(upload_to='banner', verbose_name='图片地址')
    ilnk = models.CharField(max_length=64, verbose_name='跳转链接')
    info = models.TextField(verbose_name='详情')

    class Meta:
        db_table = 'luffy_banner'
        verbose_name_plural = '轮播图表'

    def __str__(self):
        return self.title

3.编写视图函数

3.1控制返回格式 编写MyListModel继承yListModelMixins

from rest_framework.mixins import ListModelMixin
from LufeiApi.utils.common_response import MyResponse


class MyListModel(ListModelMixin):
    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return MyResponse(data=res.data)
      
    # 这样返回的格式就会安装我们封装的MyResponse返回

3.2 编写是函数

from rest_framework.viewsets import GenericViewSet
from .models import Banner
from .serializer import BannerSerializer
from LufeiApi.utils.common_mixins import MyListModel


class BannerView(GenericViewSet, MyListModel):
    queryset = Banner.objects.filter(is_show=True, is_delete=False).order_by('orders')
    serializer_class = BannerSerializer

4.编写序列化类(控制前后端传输的字段)

from rest_framework import serializers
from .models import Banner


class BannerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Banner
        fields = ['id','image','ilnk','orders','title']
        # 控制给前端的数据

总路由分发

每个app都是各自的urls.py文件
我们需要在总路由中 设置路由分发

from django.contrib import admin
from django.urls import path, include
from django.views.static import serve
from django.conf import settings

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/home/', include('LufeiApi.apps.home.urls')),
    # 每一个app都需要在这里注册一下
    path('media/<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),
]



app内子路由

from rest_framework.routers import SimpleRouter
from LufeiApi.apps.home import views
router = SimpleRouter()
router.register('banner',views.BannerView,'banner')

urlpatterns = [ ]
urlpatterns += router.urls

# 地址:ip+端口+总路由'api/v1/home/'+子路由'banner'  就可以出发对应的功能

通过simpleui录入数据

# 主站前后端分离
# 后台管理使用django 的admin做的---》simpleui

# 使用步骤:
第一步:安装simpleui
pip install django-simpleui
第二步:注册app
	'simpleui',
第三步:在对应app的admin.py中注册表
    from .models import Banner
		admin.site.register(Banner)

轮播图前端代码

组件化 首页插入轮播图组件即可

<template>
<el-carousel height="400px" :interval="5000" arrow="always">
       # 控制轮播图控件大小  轮播切换秒数
   <el-carousel-item v-for="item in img_list" :key="item.id">
        <div v-if="item.link.indexOf('http')>-1">
         # 判断轮播图地址是否是外链,外链就用a标签 不是就router-link
          <a :href="item.link">
            <img :src="item.image" :alt="item.title">
          </a>
        </div>
        <div v-else>
          <router-link :to="item.link">
            <img :src="item.image" :alt="item.title">
          </router-link>
        </div>
   </el-carousel-item>
</el-carousel>
</template>



<script>
  created() {
    this.$axios.get(this.$settings.BASE_URL + '/home/banner/').then(res => {
     # 发送请求到后端拿取轮播图数据
      if (res.data.code == 100) {
        this.img_list = res.data.data
      } else {
        this.$message(res.data.msg)
      }
    }).catch(res => {
      this.$message('轮播图服务器异常,请稍后再试')
    })
  }

</script>

/

接口添加缓存功能

有一些访问数据的接口,我们可以添加缓存,这样大大减少mysql的访问次数增加应用健壮性

eg:给banner接口加缓存

逻辑:

当用户第一次访问该接口,查看redis缓存中是否有数据 有就用缓存的没有再访问数据库

然后把数据库里面的数据 存到缓存中,用户再次访问就是直接用缓存中的数据了

from django.core.cache import cache
# cache模块可以更改配置文件 让 cache连接redis


class BannerView(GenericViewSet, ListModelMixin):
      queryset=Banner.objects.filter(is_show=True,is_delete=False).
              order_by('orders')
      serializer_class = BannerSerializer

    def list(self, request, *args, **kwargs):
        banner_list = cache.get('banner_list')
        # 通过django的缓存功能模块 去查是否有banner_list的缓存数据 如果有则用这个
        if banner_list:
            return MyResponse(result=banner_list)
        else:
            res = super().list(request, *args, **kwargs)
            # 没有则去mysql里查数据 然后更新存到缓存中
            banner_list = res.data
            cache.set('banner_list',banner_list)
            return MyResponse(result=banner_list)

数据一致性问题

如果缓存中有了数据,那就会一直使用缓存中的数据,这样就有一个问题

如果 我们更改了mysql数据,但是用户访问的还是缓存数据

由于banner接口时效性没有那么强,所以我们可以使用定时任务,每1小时清除一下redis的缓存

这样来保证 每一个小时redis数据更新一次,redis数据和mysql数据相对一致性

这里的定时任务 用的是celery模块


# 时区
app.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
app.conf.enable_utc = False

# 任务的定时配置
from celery.schedules import crontab
app.conf.beat_schedule = {
    'home_banner': {
        'task': 'celery_pack.task.home_banner_task',
        'schedule': timedelta(minutes=30),
        # 时间对象 每30分钟更新一次
        # 'schedule': crontab(hour=23,minute=58),  # 每天晚上23点58分执行
        # 'args': (300, 150),
    },
}

@app.task
def home_banner_task():
    cache.delete('banner_list')
    
    
celery -A celery_pack  worker -l info
开启执行任务

celery -A celery_pack beat -l info
开启定时器

posted @   Python-moon  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示