收货地址管理
首先就是新增地址
看图分析所需要保存的字段
因为是用户的地址,所以在users应用中的models创建模型类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 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='默认地址') ...
设置好之后执行数据库迁移
然后观察需要哪些接口
使用视图集
在users/view.py中增加代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class AddressViewSet(CreateModelMixin, UpdateModelMixin, GenericViewSet): """ 用户地址新增与修改 """ serializer_class = serializers.UserAddressSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return self.request.user.addresses.filter(is_deleted=False) def create(self, request, *args, **kwargs): """ 保存用户地址数据 :param request: :param args: :param kwargs: :return: """ # 检查用户地址数据的数量不能超过上限 # 获取用户地址的数量 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 list(self, request, *args, **kwargs): """ 用户地址列表数据 :param request: :param args: :param kwargs: :return: """ 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 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 status(self, request, pk=None): """ 设置默认地址 :param request: :param pk: :return: """ 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): """ 修改标题 :param request: :param pk: :param address_id: :return: """ address = self.get_object() serializer = serializers.AddressTitleSerializer(instance=address, data=request.data) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data)
路由设置
然后测试,成功