🏆🏆🏆教程全知識點簡介: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)