415 lines
15 KiB
Python
415 lines
15 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
@Remark: 用户地址管理
|
||
"""
|
||
import re
|
||
from rest_framework.permissions import IsAuthenticated
|
||
from rest_framework.views import APIView
|
||
from apps.address.models import *
|
||
from utils.jsonResponse import SuccessResponse,ErrorResponse
|
||
from rest_framework_simplejwt.authentication import JWTAuthentication
|
||
from utils.common import get_parameter_dic,REGEX_MOBILE
|
||
from django.core.cache import cache
|
||
from utils.locationanalysis import gettecentlnglat
|
||
from utils.serializers import CustomModelSerializer
|
||
from utils.viewset import CustomModelViewSet
|
||
from rest_framework import serializers
|
||
from rest_framework.serializers import ModelSerializer
|
||
from django.db.models import Q,F
|
||
|
||
# ================================================= #
|
||
# ************** 省市区后台管理 view ************** #
|
||
# ================================================= #
|
||
class AreaSerializer(CustomModelSerializer):
|
||
"""
|
||
地区-序列化器
|
||
"""
|
||
child_count = serializers.SerializerMethodField(read_only=True)
|
||
|
||
def get_child_count(self, instance: Area):
|
||
return Area.objects.filter(parent=instance).count()
|
||
|
||
class Meta:
|
||
model = Area
|
||
fields = "__all__"
|
||
read_only_fields = ["id"]
|
||
|
||
|
||
class AreaCreateUpdateSerializer(CustomModelSerializer):
|
||
"""
|
||
地区管理 创建/更新时的列化器
|
||
"""
|
||
|
||
class Meta:
|
||
model = Area
|
||
fields = '__all__'
|
||
|
||
|
||
class AreaViewSet(CustomModelViewSet):
|
||
"""
|
||
地区管理接口:
|
||
list:查询
|
||
create:新增
|
||
update:修改
|
||
retrieve:单例
|
||
destroy:删除
|
||
"""
|
||
queryset = Area.objects.all().order_by('id')
|
||
serializer_class = AreaSerializer
|
||
filterset_fields = ['status','id','parent']
|
||
search_fields = ('name',)
|
||
|
||
def area_root(self, request):
|
||
queryset = self.filter_queryset(self.get_queryset())
|
||
queryset = queryset.filter(parent__isnull=True).order_by('id')
|
||
serializer = AreaSerializer(queryset, many=True)
|
||
return SuccessResponse(data=serializer.data, msg="获取成功")
|
||
|
||
# ================================================= #
|
||
# ************** 省市区查询自己接口管理 view ************** #
|
||
# ================================================= #
|
||
|
||
class ProvinceAreasView(APIView):
|
||
"""
|
||
查询省数据
|
||
get:
|
||
查询省数据,补充缓存逻辑
|
||
请求方式: GET /areas/
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
|
||
def get(self, request):
|
||
#补充缓存逻辑
|
||
province_list = cache.get('province_list')
|
||
if not province_list:
|
||
try:
|
||
province_model_list = Area.objects.filter(parent__isnull=True).order_by('id')
|
||
province_list = []
|
||
for province_model in province_model_list:
|
||
province_list.append({'id': province_model.id,'name': province_model.name})
|
||
# 增加: 缓存省级数据
|
||
cache.set('province_list', province_list, 3600)
|
||
except Exception as e:
|
||
return ErrorResponse(msg='省份数据错误')
|
||
return SuccessResponse(data=province_list,msg='success')
|
||
|
||
class SubAreasView(APIView):
|
||
"""
|
||
查询市或区数据
|
||
get:
|
||
子级地区:市和区县
|
||
请求方式: GET /areas/(?P<pk>[1-9]\d+)/
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
|
||
def get(self, request, pk):
|
||
"""提供市或区地区数据
|
||
1.查询市或区数据
|
||
2.序列化市或区数据
|
||
3.响应市或区数据
|
||
4.补充缓存数据
|
||
"""
|
||
# 判断是否有缓存
|
||
sub_data = cache.get('sub_area_' + pk)
|
||
|
||
if not sub_data:
|
||
|
||
# 1.查询市或区数据
|
||
try:
|
||
sub_model_list = Area.objects.filter(parent=pk).order_by('id')
|
||
# 查询市或区的父级
|
||
parent_model = Area.objects.get(id=pk)
|
||
|
||
|
||
# 2.序列化市或区数据
|
||
sub_list = []
|
||
for sub_model in sub_model_list:
|
||
sub_list.append({'id': sub_model.id, 'name': sub_model.name})
|
||
|
||
sub_data = {
|
||
'id':parent_model.id, # pk
|
||
'name':parent_model.name,
|
||
'subs': sub_list
|
||
}
|
||
|
||
# 缓存市或区数据
|
||
cache.set('sub_area_' + pk, sub_data, 3600)
|
||
except Exception as e:
|
||
return ErrorResponse(msg='城市或区县数据错误')
|
||
|
||
# 3.响应市或区数据
|
||
return SuccessResponse(data=sub_data,msg="success")
|
||
|
||
def CommentTree(datas):
|
||
"""
|
||
获取结构树
|
||
:param datas:
|
||
:return:
|
||
"""
|
||
lists=[]
|
||
tree={}
|
||
parent_id=''
|
||
for s in datas:
|
||
s['childlist'] = []
|
||
tree[str(s['id'])]=s
|
||
root=None
|
||
for i in datas:
|
||
if not i['pid']:#判断根
|
||
root=tree[str(i['id'])]
|
||
lists.append(root)#添加到列表
|
||
if 'childlist' not in tree[str(i['id'])]:
|
||
tree[str(i['id'])]['childlist'] = []
|
||
else:
|
||
parent_id=str(i['pid'])
|
||
if 'childlist' not in tree[parent_id]:
|
||
tree[parent_id]['childlist']=[]
|
||
tree[parent_id]['childlist'].append(tree[str(i['id'])])
|
||
return lists
|
||
|
||
class Area2Serializer(CustomModelSerializer):
|
||
"""
|
||
省市区 -序列化器
|
||
"""
|
||
pid = serializers.CharField(source="parent_id")
|
||
|
||
class Meta:
|
||
model = Area
|
||
read_only_fields = ["id"]
|
||
fields = ['id','name','pid','level','citycode']
|
||
# exclude = ['password']
|
||
# extra_kwargs = {
|
||
# 'post': {'required': False},
|
||
# }
|
||
|
||
class GetProvinceAreasListView(APIView):
|
||
"""
|
||
递归获取所有省市区
|
||
get:
|
||
递归获取所有省市区
|
||
id:区域编码,为空表示获取所有一级
|
||
subdistrict:取值0-2(0:不返回下级行政区、1:返回下一级行政区、2:返回下两级行政区)
|
||
"""
|
||
permission_classes = []
|
||
authentication_classes = []
|
||
# permission_classes = [IsAuthenticated]
|
||
# authentication_classes = [JWTAuthentication]
|
||
|
||
def get(self, request):
|
||
reqData = get_parameter_dic(request)
|
||
id = reqData.get('id',"")
|
||
subdistrict = int(reqData.get('subdistrict',0))
|
||
queryset = Area.objects.filter(status=True).order_by('id')
|
||
if subdistrict == 0:
|
||
if id:
|
||
queryset = queryset.filter(id = id)
|
||
else:
|
||
queryset = queryset.filter(level=1)
|
||
elif subdistrict == 1:
|
||
if id:
|
||
queryset = queryset.filter(Q(id = id)|Q(parent_id=id))
|
||
else:
|
||
queryset = queryset.filter(level__in=[1,2])
|
||
else:
|
||
if id:
|
||
queryset = queryset.filter(Q(id = id)|Q(parent_id=id)|Q(parent__parent_id=id))
|
||
queryset_ser = Area2Serializer(queryset,many=True)
|
||
queryset_list = CommentTree(queryset_ser.data)
|
||
return SuccessResponse(data=queryset_list, msg='success')
|
||
# ================================================= #
|
||
# ************** 根据详细地址获取经纬度信息 view ************** #
|
||
# ================================================= #
|
||
class GetAddressAccuracyView(APIView):
|
||
"""
|
||
get:
|
||
根据详细地址信息获取经纬度
|
||
【参数】:address 为要查询的详细地址
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
|
||
def get(self, request):
|
||
address = get_parameter_dic(request)['address']
|
||
if address is None:
|
||
return ErrorResponse(msg="要查询的地址不能为空")
|
||
data = gettecentlnglat(address)
|
||
return SuccessResponse(data=data,msg="success")
|
||
|
||
|
||
# ================================================= #
|
||
# ************** 前端用户地址操作 view ************** #
|
||
# ================================================= #
|
||
class AddressSerializer(ModelSerializer):
|
||
"""
|
||
用户地址 简单序列化器
|
||
"""
|
||
|
||
|
||
class Meta:
|
||
model = Address
|
||
fields = "__all__"
|
||
read_only_fields = ["id"]
|
||
|
||
def create(self, validated_data):#有外键的新增数据时要自定义create添加外键数据
|
||
return Address.objects.create(user=self.context["user"], **validated_data)
|
||
|
||
class GetAssressesListView(APIView):
|
||
"""
|
||
用户查询地址列表/获取默认地址接口
|
||
get:
|
||
【参数】type=default 获取默认地址,不传type默认获取地址列表
|
||
【参数】type=detail 获取单个地址详情,后面需跟上地址的id
|
||
【参数】type=all 获取地址列表
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
serializer_class = AddressSerializer
|
||
|
||
def get(self, request):
|
||
type = get_parameter_dic(request)['type']
|
||
user = request.user
|
||
if type == "default":
|
||
# queryset = Address.objects.filter(id=user.default_address_id).first()
|
||
queryset = Address.objects.filter(user=user, is_deleted=False,is_default=True).first()
|
||
serializer = self.serializer_class(queryset,many=False)
|
||
return SuccessResponse(data=serializer.data, msg="success")
|
||
elif type == "detail":
|
||
id = get_parameter_dic(request)['id']
|
||
if id is None:
|
||
return ErrorResponse(msg="id不能为空")
|
||
queryset = Address.objects.filter(id=id,user=user,is_deleted=False).first()
|
||
serializer = self.serializer_class(queryset, many=False)
|
||
return SuccessResponse(data=serializer.data, msg="success")
|
||
else:
|
||
queryset = Address.objects.filter(user=user, is_deleted=False)
|
||
serializer = self.serializer_class(queryset,many=True)
|
||
return SuccessResponse(data=serializer.data,msg="success")
|
||
|
||
class CreateUpdateAssressesView(APIView):
|
||
"""
|
||
用户地址新增/修改管理接口
|
||
post:
|
||
【参数】提交的参数名,与获取地址列表名保持一致
|
||
receiver 收货人姓名
|
||
province 省
|
||
city 市
|
||
district 区
|
||
street 街道
|
||
place 详细地址
|
||
mobile 手机号
|
||
参数中有id字段表示修改,没有id则表示新增
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
serializer_class = AddressSerializer
|
||
|
||
def post(self, request):
|
||
reqData = get_parameter_dic(request)
|
||
mobile = reqData.get('mobile',None)
|
||
if not re.match(REGEX_MOBILE, mobile):
|
||
return ErrorResponse(msg="手机号不正确")
|
||
user = request.user
|
||
type = reqData.get('type','add')
|
||
receiver = reqData.get('receiver',None)
|
||
province = reqData.get('province',None)
|
||
city = reqData.get('city',None)
|
||
district = reqData.get('district',None)
|
||
street = reqData.get('street',None)
|
||
place = reqData.get('place',None)
|
||
latitude=reqData.get('latitude',None)
|
||
longitude=reqData.get('longitude',None)
|
||
is_default = int(reqData.get('is_default',0))
|
||
|
||
if is_default not in [0,1]:
|
||
return ErrorResponse(msg="is_default类型错误")
|
||
|
||
if type=="add":#新增
|
||
queryset = Address.objects.filter(user=user,is_deleted=False,is_default=True)
|
||
if queryset:
|
||
if is_default:
|
||
queryset.update(is_default=False)
|
||
|
||
myaddress = Address.objects.create(user=user,receiver=receiver,province=province,city=city,district=district,street=street,place=place,mobile=mobile,latitude=latitude,longitude=longitude,is_default=is_default)
|
||
return SuccessResponse(data={'addressid':myaddress.id},msg='success')
|
||
elif type=='edit':
|
||
id = get_parameter_dic(request)['id']
|
||
instance = Address.objects.filter(id=id,user=user).first()
|
||
if instance:#有这个地址数据
|
||
otheraddresslist = Address.objects.filter(user=user,is_deleted=False).exclude(id=id)
|
||
if is_default: # 设置默认
|
||
if otheraddresslist: # 取消其他地址的默认
|
||
otheraddresslist.update(is_default=False)
|
||
instance.is_default = True
|
||
else: # 取消默认
|
||
instance.is_default = False
|
||
|
||
instance.receiver = receiver
|
||
instance.province = province
|
||
instance.city = city
|
||
instance.district = district
|
||
instance.receiver = receiver
|
||
instance.street = street
|
||
instance.place = place
|
||
instance.mobile = mobile
|
||
instance.longitude = longitude
|
||
instance.latitude = latitude
|
||
instance.save()
|
||
return SuccessResponse(msg='修改成功')
|
||
else:
|
||
return ErrorResponse(msg="修改失败")
|
||
else:
|
||
return ErrorResponse(msg="type类型错误")
|
||
|
||
class DeleteAssressesView(APIView):
|
||
"""
|
||
用户地址删除接口
|
||
get:
|
||
【参数】id:需要删除的地址id
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
serializer_class = AddressSerializer
|
||
|
||
def get(self, request):
|
||
id = get_parameter_dic(request)['id']
|
||
if id is None:
|
||
return ErrorResponse(msg="id不能为空")
|
||
user = request.user
|
||
queryset = Address.objects.filter(Q(id=id)&Q(user=user)&Q(is_deleted=False))
|
||
if queryset:
|
||
queryset.update(is_deleted=True)
|
||
return SuccessResponse(msg='success')
|
||
return ErrorResponse(msg="删除失败")
|
||
|
||
class SetDefaultAssressesView(APIView):
|
||
"""
|
||
用户设置默认地址接口
|
||
post:
|
||
【参数】id:设置默认的地址id,is_default:0非默认地址,1默认地址
|
||
"""
|
||
permission_classes = [IsAuthenticated]
|
||
authentication_classes = [JWTAuthentication]
|
||
serializer_class = AddressSerializer
|
||
|
||
def post(self, request):
|
||
id = get_parameter_dic(request)['id']
|
||
is_default = get_parameter_dic(request)['is_default']
|
||
if id is None:
|
||
return ErrorResponse(msg="id不能为空")
|
||
user = request.user
|
||
otheraddresslist = Address.objects.filter(user=user).exclude(id=id)
|
||
currentaddress = Address.objects.filter(id=id,user=user).first()
|
||
if not currentaddress:
|
||
return ErrorResponse(msg="设置失败")
|
||
if is_default:#设置默认
|
||
currentaddress.is_default = True
|
||
currentaddress.save()
|
||
if otheraddresslist:#取消其他地址的默认
|
||
otheraddresslist.update(is_default=False)
|
||
return SuccessResponse(msg='success')
|
||
else:#取消默认
|
||
currentaddress.is_default = False
|
||
currentaddress.save()
|
||
return SuccessResponse(msg='success') |