動態

詳情 返回 返回

【Django開發】django美多商某城項目完整開發4.0第11篇:shou貨地址,使用緩存【附代碼文檔】 - 動態 詳情

🏆🏆🏆教程全知識點簡介: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使用、回調處理)、用户中心個人信息。

<!-- start:bj1 -->

📚📚倉庫code.zip 👉直接-->:   https://gitlab.com/yinuo_112/Backend/-/blob/main/Django/djang...    🍅🍅

<!-- end:bj1 -->

✨ 本教程項目亮點

🧠 知識體系完整:覆蓋從基礎原理、核心方法到高階應用的全流程內容
💻 全技術鏈覆蓋:完整前後端技術棧,涵蓋開發必備技能
🚀 從零到實戰:適合 0 基礎入門到提升,循序漸進掌握核心能力
📚 豐富文檔與代碼示例:涵蓋多種場景,可運行、可複用
🛠 工作與學習雙參考:不僅適合系統化學習,更可作為日常開發中的查閲手冊
🧩 模塊化知識結構:按知識點分章節,便於快速定位和複習
📈 長期可用的技術積累:不止一次學習,而是能伴隨工作與項目長期參考

🎯🎯🎯全教程總章節


🚀🚀🚀本篇主要內容

shou貨地址

在這個頁面中, 要實現用户地址的管理,主要的業務邏輯有:

  • 省市區地址的數據庫建立與查詢
  • 用户地址的增刪改查處理
  • 設置默認地址
  • 設置地址標題

    主要講解省市區地址的三級聯動和緩存,其餘留給大家自己來實現。

學習目標:

  • 省市區三級聯動
  • 在Django REST framework中使用緩存

使用緩存

省市區的數據是經常被用户查詢使用的,而且數據基本不變化,所以 可以將省市區數據進行緩存處理,減少數據庫的查詢次數。

在Django REST framework中使用緩存,可以通過drf-extensions擴展來實現。

關於擴展使用緩存的文檔,可參考鏈接http://chibisov.github.io/drf-extensions/docs/#caching

安裝

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 文檔

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)
user avatar ting_61d6d9790dee8 頭像 xiaoxxuejishu 頭像 histry 頭像 abc-x 頭像 ldh-blog 頭像 q_bit 頭像 bizseerbishikeji 頭像 ruanjiankaifa_xiaofanya 頭像 yayujs 頭像 liudamao 頭像 xuri 頭像 jiaolvdekaixinguo 頭像
點贊 27 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.