【Django开发】django美多商某城项目完整开发4.0第11篇:shou货地址,使用缓存【附代码文档】

举报
程序员一诺python 发表于 2025/09/15 20:45:26 2025/09/15
【摘要】 1.邮件验证系统包括Django发送邮件、保存邮箱并发送验证邮件、Celery使用Django配置文件设置。2. 地址管理涵盖shou货地址、省市区地址查询、数据库建表、后端接口设计、前端实现、缓存使用(安装、使用方法、省市区视图缓存、缓存数据保存位置和有效期设置)、用户地址管理。3. 数据库设计包括用户部分、产品部分、数据库表设计、表结构、数据库模型类。4. 容器化部署涵盖D

🏆🏆🏆教程全知识点简介:1.邮件验证系统包括Django发送邮件、保存邮箱并发送验证邮件、Celery使用Django配置文件设置。2. 地址管理涵盖shou货地址、省市区地址查询、数据库建表、后端接口设计、前端实现、缓存使用(安装、使用方法、省市区视图缓存、缓存数据保存位置和有效期设置)、用户地址管理。3. 数据库设计包括用户部分、产品部分、数据库表设计、表结构、数据库模型类。4. 容器化部署涵盖Docker使用(Ubuntu安装、启动停止、镜像操作)、FastDFS客户端与自定义文件存储系统、页面静态化、定时任务、静态化首页脚本。5. 产品系统包括产品详情页、异步任务触发、脚本工具、用户浏览历史记录(保存、查看)。6. 产品模式涵盖B2B企业对企业、C2C个人对个人、O2O线上到线下、开发流程、需求分析。7. 购wu车系统包括购wu车管理、购wu车数据存储设计(Redis保存已登录用户)、添加到购wu车、查询购wu车数据、登录合并购wu车。8. 订order单系统涵盖提交订order单、我的订order单、订order单评价、订order单结算、保存订order单、MySQL事务隔离级别修改、下单成功页面。9. 搜索系统包括产品搜索、搜索引擎原理、Elasticsearch、Docker安装Elasticsearch扩展、前端实现。10. 支fu系统涉及 集成、Xadmin管理后台。11. 项目配置包括项目准备、配置文件修改、数据库配置、Redis配置、本地化语言时区、异常处理、日志记录。12. 用户认证系统涵盖图片验证码、域名设置、前端Vue代码、跨域CORS、Celery发送短信、账号存在判断、JWT认证(JWT概念、构成、应用、Django REST framework JWT)、 登录(登录流程、模型类创建、urllib使用、回调处理)、用户中心个人信息。


📚📚仓库code.zip 👉直接-->:   https://gitee.com/yinuo112/Backend/blob/master/Django/django美多商某城项目完整开发4.0/note.md    🍅🍅

✨ 本教程项目亮点

🧠 知识体系完整:覆盖从基础原理、核心方法到高阶应用的全流程内容
💻 全技术链覆盖:完整前后端技术栈,涵盖开发必备技能
🚀 从零到实战:适合 0 基础入门到提升,循序渐进掌握核心能力
📚 丰富文档与代码示例:涵盖多种场景,可运行、可复用
🛠 工作与学习双参考:不仅适合系统化学习,更可作为日常开发中的查阅手册
🧩 模块化知识结构:按知识点分章节,便于快速定位和复习
📈 长期可用的技术积累:不止一次学习,而是能伴随工作与项目长期参考


🎯🎯🎯全教程总章节


🚀🚀🚀本篇主要内容

shou货地址

在这个页面中, 要实现用户地址的管理,主要的业务逻辑有:

  • 省市区地址的数据库建立与查询
  • 用户地址的增删改查处理
  • 设置默认地址
  • 设置地址标题

主要讲解省市区地址的三级联动和缓存,其余留给大家自己来实现。

学习目标:

  • 省市区三级联动
  • 在Django REST framework中使用缓存

使用缓存

省市区的数据是经常被用户查询使用的,而且数据基本不变化,所以 可以将省市区数据进行缓存处理,减少数据库的查询次数。

在Django REST framework中使用缓存,可以通过drf-extensions扩展来实现。

关于扩展使用缓存的文档,可参考链接[

安装

pip install drf-extensions

使用方法

1) 直接添加装饰器

可以在使用rest_framework_extensions.cache.decorators中的cache_response装饰器来装饰返回数据的类视图的对象方法,如

[Codecademy Python]

class CityView(views.APIView):
    @cache_response()
    def get(self, request, *args, **kwargs):
        ...

cache_response装饰器可以接收两个参数

@cache_response(timeout=60*60, cache='default')
  • timeout 缓存时间
  • cache 缓存使用的Django缓存后端(即CACHES配置中的键名称)

如果在使用cache_response装饰器时未指明timeout或者cache参数,则会使用配置文件中的默认配置,可以通过如下方法指明:

# DRF扩展


REST_FRAMEWORK_EXTENSIONS = {
    # 缓存时间
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
    # 缓存存储
    'DEFAULT_USE_CACHE': 'default',
}
  • DEFAULT_CACHE_RESPONSE_TIMEOUT 缓存有效期,单位秒
  • DEFAULT_USE_CACHE 缓存的存储方式,与配置文件中的CACHES的键对应。

注意,cache_response装饰器既可以装饰在类视图中的get方法上,也可以装饰在REST framework扩展类提供的list或retrieve方法上。使用cache_response装饰器无需使用method_decorator进行转换。

2)使用drf-extensions提供的扩展类

drf-extensions扩展对于缓存提供了三个扩展类:

  • ListCacheResponseMixin

用于缓存返回列表数据的视图,与ListModelMixin扩展类配合使用,实际是为list方法添加了cache_response装饰器

  • RetrieveCacheResponseMixin

用于缓存返回单一数据的视图,与RetrieveModelMixin扩展类配合使用,实际是为retrieve方法添加了cache_response装饰器

  • CacheResponseMixin

为视图集同时补充List和Retrieve两种缓存,与ListModelMixin和RetrieveModelMixin一起配合使用。

三个扩展类都是在rest_framework_extensions.cache.mixins中。

为省市区视图添加缓存

因为省市区视图使用了视图集,并且视图集中有提供ListModelMixin和RetrieveModelMixin的扩展(由ReadOnlyModelViewSet提供),所以可以直接添加CacheResponseMixin扩展类。

修改返回省市区信息的视图

from rest_framework_extensions.cache.mixins import CacheResponseMixin

class AreasViewSet(CacheResponseMixin, ReadOnlyModelViewSet):
    """
    行政区划信息
    """
    pagination_class = None  # 区划信息不分页

    def get_queryset(self):
        """
        提供数据集
        """
        if self.action == 'list':
            return Area.objects.filter(parent=None)
        else:
            return Area.objects.all()

    def get_serializer_class(self):
        """
        提供序列化器
        """
        if self.action == 'list':
            return AreaSerializer
        else:
            return SubAreaSerializer

缓存数据保存位置与有效期的设置

想把缓存数据保存在redis中,且设置有效期,可以通过在配置文件中定义的方式来实现。

在配置文件中增加

# DRF扩展


REST_FRAMEWORK_EXTENSIONS = {
    # 缓存时间
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
    # 缓存存储
    'DEFAULT_USE_CACHE': 'default',
}

用户地址管理

为保存用户的地址信息,创建数据库表,在users/models.py中定义模型类

class Address(BaseModel):
    """
    用户地址
    """
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name='用户')
    title = models.CharField(max_length=20, verbose_name='地址名称')
    receiver = models.CharField(max_length=20, verbose_name='shou货人')
    province = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='province_addresses', verbose_name='省')
    city = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='city_addresses', verbose_name='市')
    district = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='district_addresses', verbose_name='区')
    place = models.CharField(max_length=50, verbose_name='地址')
    mobile = models.CharField(max_length=11, verbose_name='手机')
    tel = models.CharField(max_length=20, null=True, blank=True, default='', verbose_name='固定电话')
    email = models.CharField(max_length=30, null=True, blank=True, default='', verbose_name='电子邮箱')
    is_deleted = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'tb_address'
        verbose_name = '用户地址'
        verbose_name_plural = verbose_name
        ordering = ['-update_time']

说明:

  • Address模型类中的外键指向Areas/models里面的Area,指明外键ForeignKey时,可以使用字符串应用名.模型类名来定义

  • related_name 在进行反向关联查询时使用的属性,如 city = models.ForeignKey('areas.Area', related_name='city_addresses')表示可以通过Area对象.city_addresses属性获取所有相关的city数据。

  • ordering 表名在进行Address查询时,默认使用的排序方式

为User模型类添加默认地址

class User(AbstractUser):
    ...
    default_address = models.ForeignKey('Address', related_name='users', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='默认地址')
    ...

用户地址管理代码

[Keras 文档]

后端

在users/views.py中添加视图

[PyPDF2 文档] ```python class AddressViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, GenericViewSet): """ 用户地址新增与修改 """ serializer_class = serializers.UserAddressSerializer permissions = [IsAuthenticated]

def get_queryset(self):
    return self.request.user.addresses.filter(is_deleted=False)

def list(self, request, *args, **kwargs):
    """
    用户地址列表数据
    """
    queryset = self.get_queryset()
    serializer = self.get_serializer(queryset, many=True)
    user = self.request.user
    return Response({
        'user_id': user.id,
        'default_address_id': user.default_address_id,
        'limit': constants.USER_ADDRESS_COUNTS_LIMIT,
        'addresses': serializer.data,
    })

def create(self, request, *args, **kwargs):
    """
    保存用户地址数据
    """
    # 检查用户地址数据数目不能超过上限
    count = request.user.addresses.count()
    if count >= constants.USER_ADDRESS_COUNTS_LIMIT:
        return Response({'message': '保存地址数据已达到上限'}, status=status.HTTP_400_BAD_REQUEST)

    return super().create(request, *args, **kwargs)

def destroy(self, request, *args, **kwargs):
    """
    处理删除
    """
    address = self.get_object()

    # 进行逻辑删除
    address.is_deleted = True
    address.save()

    return Response(status=status.HTTP_204_NO_CONTENT)

@action(methods=['put'], detail=True)
def status(self, request, pk=None, address_id=None):
    """
    设置默认地址
    """
    address = self.get_object()
    request.user.default_address = address
    request.user.save()
    return Response({'message': 'OK'}, status=status.HTTP_200_OK)

@action(methods=['put'], detail=True)
def title(self, request, pk=None, address_id=None):
    """
    修改标题
    """
    address = self.get_object()
    serializer = serializers.AddressTitleSerializer(instance=address, data=request.data)
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(ser
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。