为省、市、区添加缓存
配置缓存
1.安装扩展模块 drf-extensions
1 2 3 4 5 6 7 8 9 10 11 12 13
| leazhi@ubuntuhome:~$ workon haoke_small (haoke_small) leazhi@ubuntuhome:~$ pip install drf-extensions Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting drf-extensions Downloading https://pypi.tuna.tsinghua.edu.cn/packages/58/15/ee46fa8293a51b68c60699806c0c2f55ff527613d83739e27b8f85444990/drf_extensions-0.7.1-py2.py3-none-any.whl (21 kB) Requirement already satisfied: djangorestframework>=3.9.3 in ./.env/haoke_small/lib/python3.10/site-packages (from drf-extensions) (3.14.0) Requirement already satisfied: django>=3.0 in ./.env/haoke_small/lib/python3.10/site-packages (from djangorestframework>=3.9.3->drf-extensions) (3.2.20) Requirement already satisfied: pytz in ./.env/haoke_small/lib/python3.10/site-packages (from djangorestframework>=3.9.3->drf-extensions) (2023.3) Requirement already satisfied: asgiref<4,>=3.3.2 in ./.env/haoke_small/lib/python3.10/site-packages (from django>=3.0->djangorestframework>=3.9.3->drf-extensions) (3.7.2) Requirement already satisfied: sqlparse>=0.2.2 in ./.env/haoke_small/lib/python3.10/site-packages (from django>=3.0->djangorestframework>=3.9.3->drf-extensions) (0.4.4) Requirement already satisfied: typing-extensions>=4 in ./.env/haoke_small/lib/python3.10/site-packages (from asgiref<4,>=3.3.2->django>=3.0->djangorestframework>=3.9.3->drf-extensions) (4.7.1) Installing collected packages: drf-extensions Successfully installed drf-extensions-0.7.1
|
2.编辑配置文件 dev.py,在文件默认添加如下配置:
1 2 3 4 5 6 7 8 9 10 11 12
|
...
REST_FRAMEWORK_EXTENSIONS = { 'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60 * 24, 'DEFAULT_USE_CACHE': 'default', }
|
为省市区数据缓存添加视图:
1.编辑子应用 areas 目录下的视图文件 views.py,添加如下视图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
...
from rest_framework_extensions.cache.mixins import CacheResponseMixin
...
class AreasViewSet(CacheResponseMixin, ModelViewSet): 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 AreaModelSerializer else: return SubAreaModelSerializer
def list(self, request, *args, **kwargs): queryset = self.get_queryset() serializer = self.get_serializer_class()(queryset, many=True) return render(request, serializer.data, status=200)
|
收获地址的增、删、改、查
准备工作
1.在项目子目录 haoke 目录下新建一个包目录 utils,然后在该目录下新建一个 models.py 文件,添加如下模型类:
1 2 3 4 5 6 7 8 9 10
| # utils/models.py
from django.db import models
class BaseModel (models.Model): create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta: abstract = True # 说明是抽象模型类,用于继承使用,数据库迁移时不会创建 BaseModel 的表
|
2.编辑子应用 users 目录下的 models.py,添加如下模型类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
...
from haoke.utils.models import BaseModel
...
class User(AbstractUser):
...
email_active = models.BooleanField(default=False, verbose_name='邮箱是否激活') default_address = models.ForeignKey('Address', related_name='users', null=True, blank=True, on_delete=models.SET_NULL, verbose_name='默认地址')
class Meta: ...
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='收货人') 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
|
3.数据迁移,生成表:
1 2 3 4
| (haoke_small) leazhi@ubuntuhome:~$ cd small/haoke/ (haoke_small) leazhi@ubuntuhome:~/small/haoke$ python manage.py makemigrations
(haoke_small) leazhi@ubuntuhome:~/small/haoke$ python manage.py migrate
|
增
添加序列化器
编辑子应用 users 目录下的 serializers.py 文件,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
|
...
from .models import User,Address class UserAddressSerializer(serializers.ModelSerializer): """ 用户地址序列化器 """
province = serializers.StringRelateField(read_only=True) city = serializers.StringRelateField(read_only=True) district = serializers.StringRelateField(read_only=True) province_id = serializers.IntegerField(read_only=True) city_id = serializers.IntegerField(read_only=True) district_id = serializers.IntegerField(read_only=True) class Meta: model = Address exclude = ('user', 'is_deleted', 'create_time', 'update_time')
def create(self, validated_data): """ 新增保存 :param validated_data: :return: """ if not re.match(r'1[3-9]\d{9}', validated_data['mobile']): raise serializers.ValidationError('手机号格式不正确') validated_data['user'] = self.context['request'].user
return super().create(validated_data)
class AddressTitleSerializer(serializers.ModelSerializer): """ 地址标题序列化器 """
class Meta: model = Address fields = ('title',)
|
添加视图集
1.编辑子应用 users 目录下的 views.py 文件,导入 ModelViewSet 类,并继承 ModelViewSet 类,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
...
from rest_framework.viewsets import ModelViewSet from users.serializers import UserAddressSerializer, AddressTitleSerializer
...
class AddressViewSet(ModelViewSet): """ 用户地址 """
serializer_class = UserAddressSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self): return self.request.user.addresses.filter(is_deleted=False)
def list(self, request, *args, **kwargs): """ 用户地址列表数据 :param request: :param args: :param kwargs: :return: """
queryset = self.get_queryset().filter(user=request.user) serializer = self.get_serializer(queryset, many=True)
use = serializer.request.user
return Response({ 'addresses': serializer.data, 'limit': 20, 'default_address_id': user.default_address_id, })
def create(self, request, *args, **kwargs):
count = request.user.addresses.count()
if count >= 20: return Response({'message': '收货地址最多添加20条'}, status=status.HTTP_400_BAD_REQUEST)
return super().create(request, *args, **kwargs) def destroy(self, request, *args, **kwargs): """ 处理删除的 :param request: :param args: :param kwargs: :return: """ address = self.get_object()
address.is_deleted = True
address.save()
return Response(status=status.HTTP_204_NO_CONTENT)
@action(methods=['put'], detail=True) def title(self, request, pk=None): address = self.get_object()
ser =AddressTitleSerializer(instance= address , data= request.data)
ser.is_valid()
ser.save()
return Response(ser.data)
@action(methods=['put'], detail=True) def status(self,request, pk):
address = self.get_object()
request.user.default_address = address
request.user.save()
return Response({'message': 'OK'}, status=status.HTTP_200_OK)
|
添加访问路由
编辑子应用 users 目录下的 urls.py 文件,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
...
from rest_framework.routers import DefaultRouter
...
router = DefaultRouter() router.register('addresses', views.AddressViewSet, basename='addresses') urlpatterns += router.urls
|