在很多时候,项目中难免用到省市区地址。所以数据库的表设计比较重要,可以直接将省市区的数据放在同一个表中,然后采用自关联法来实现三级联动。
一、models中创建数据模型
class Area(models.Model):
"""
行政区划
"""
name = models.CharField(max_length=20, verbose_name='名称')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='subs', null=True, blank=True, verbose_name='上级行政区划')
class Meta:
db_table = 'tb_areas'
verbose_name = '行政区划'
verbose_name_plural = '行政区划'
def __str__(self):
return self.name
二、后端接口设计
在端口设计是直接分成两个请求,因为省份和市区确定之后,区县就确定了。
1、请求省份数据
1、创建序列化器
由于返回的数据不是什么隐私数据,所以在序列化器中直接设置需要的字段即可
class AreaSerializer(serializers.ModelSerializer):
"""
行政区划信息序列化器
"""
class Meta:
model = Area
fields = ('id', 'name')
2、创建视图
指定序列化器和查询集,ListAPIView提供有对应的get方法,使用可以直接拿来用。列表视图
class AreaListView(ListAPIView):
"""查询所有值"""
serializer_class = AreasSerializer
queryset = Area.objects.filter(parent=None)
3.接收前端请求 urls设计
# 查询所有
path('areas/', views.AreaListView.as_view()),
2、请求市区数据
1、创建序列化器
不校验只返回
class SubAreaSerializer(serializers.ModelSerializer):
"""
子行政区划信息序列化器
"""
subs = AreaSerializer(many=True, read_only=True)
class Meta:
model = Area
fields = ('id', 'name', 'subs')
2、创建视图
RetrieveAPIView有对应的get方法,用于详情视图的请求
class AreaDetailView(RetrieveAPIView):
""""""
serializer_class = SubsSerializer
queryset = Area.objects.all()
3、接收前端请求,设计urls
# 查询对应的市
path('areas/<int:pk>/', views.AreaDetailView.as_view()),
三、使用缓存技术
省市区的数据是经常被用户查询使用的,而且数据基本不变化,所以我们可以将省市区数据进行缓存处理,减少数据库的查询次数。
在Django REST framework中使用缓存,可以通过drf-extensions
扩展来实现。
关于扩展使用缓存的文档,可参考链接Django Rest Framework extensions documentation
1、安装
pip install drf-extensions
2、在dev配置中添加缓存的设置
# DRF扩展
REST_FRAMEWORK_EXTENSIONS = {
# 缓存时间
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
# 缓存存储
'DEFAULT_USE_CACHE': 'default',
}
3、升级视图类方法
-
ListCacheResponseMixin
用于缓存返回列表数据的视图,与ListModelMixin扩展类配合使用,实际是为list方法添加了cache_response装饰器
-
RetrieveCacheResponseMixin
用于缓存返回单一数据的视图,与RetrieveModelMixin扩展类配合使用,实际是为retrieve方法添加了cache_response装饰器
-
CacheResponseMixin
为视图集同时补充List和Retrieve两种缓存,与ListModelMixin和RetrieveModelMixin一起配合使用。
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