在用户录入地址时,需要进行省市区的选择。在页面加载时,向后端请求省份数据,当用户选择确定省份后,向后端请求该省份的城市数据;在用户选择确定城市数据后,向后端请求该城市的区县信息。我们把这个过程称为省市区三级联动。
cd到apps文件夹下创建
python ../../manage.py startapp areas
安装完之后注意配置设置文件:
INSTALLED_APPS = [
‘areas.apps.AreasConfig‘,#省市区数据
]
还有系统urls的配置和admin后台管理也要写一下
from django.db import models
# Create your models here.
class Areas(models.Model):
name = models.CharField(max_length=50, verbose_name='地名')
# 外键链接自己,ondelete是当删除时和主表的行为
pid = models.ForeignKey('self', verbose_name='父级的行政区域id', on_delete=models.SET_NULL, related_name='addinfo', null=True, blank=True)
# on_delete = models.CASCADE # 删除关联数据的时候,与之的关联也删除
# on_delete = models.DO_NOTHING # 不作操作
# on_delete = models.PROTECT # 删除关联就保存,保护
# on_delete = models.SET_DEFAULT # 与之关联设为默认值
# on_delete = models.SET_NULL # 与之关联设为空
def __str__(self):
return self.name
class Meta:
db_table = 'areas'
verbose_name_plural = '地区'
模型类代码说明:
pid = models.ForeignKey('self', verbose_name='父级的行政区域id', on_delete=models.SET_NULL, related_name='addinfo', null=True, blank=True)
每次对models模型文件修改都要进行数据迁移,终端执行
python manage.py makemigrations
python manage.py migrate
然后下载数据库文件省市区的areas.sql:
https://download.csdn.net/download/paul0926/11251780
终端到这个文件的目录里然后倒入到你的数据库中
mysql -uroot -p shanghui < areas.sql
导完查看一下是否成功
这里使用ReadOnlyModelViewSet,因为能根据不同的请求指定不同的序列化器,
from django.shortcuts import render
from rest_framework.viewsets import *
from .serializers import *
from .models import *
# Create your views here.
class AreasInfoView(ReadOnlyModelViewSet):
"""提供省市区三级联动数据"""
# 禁用分页
pagination_class = None
# 指定要输出的数据来自哪个查询集
# queryset = Area.objects.all()
def get_queryset(self):
"""根据请求的行为,过滤不同的行为对应的序列化器需要的数据"""
if self.action == 'list':
return Areas.objects.filter(pid=None) # 只有当pid=None 返回的是省级数据
else:
return Areas.objects.all()
# 指定序列化器
# serializer_class = ‘序列化器‘
def get_serializer_class(self):
"""根据请求的行为,指定不同的序列化器"""
if self.action == 'list':
return AreaInfoSer
else:
return NextAreasInfoSer
在areas文件夹下新建serializers.py文件写序列化器类
from rest_framework import serializers
from . import models
class AreaInfoSer(serializers.ModelSerializer):
class Meta:
model = models.Areas
fields = ('id', 'name')
class NextAreasInfoSer(serializers.ModelSerializer):
# 嵌套序列化器,得到自己想要的数据
addinfo = AreaInfoSer(many=True, read_only=True)
# 这个是返回字符串显示的是__str__方法返回的内容。
# addinfo = serializers.StringRelatedField(many=True, read_only=True)
# 不写的时候默认是PrimaryKeyrelatedField,也就是显示id
# 要展现他的下一级
class Meta:
model = models.Areas
fields = ('id', 'name', 'addinfo')
第一个序列化器就是展示地区名,第二个序列化器是为了展示他的下一级,比如查看浙江省,附带他的市级行政区,注意这个返回第一个序列化器内容的名字需要和上面模型类的related_name名字一致
当使用viewsets类的时候都推荐使用路由自动配置路径
from django.conf.urls import url, include
from .views import *
from rest_framework import routers
router = routers.DefaultRouter()
# 第一个参数是路径
router.register(r'info', AreasInfoView, base_name='info')
urlpatterns = [
url(r'', include(router.urls))
]
django如何配置接口文档查看:https://blog.csdn.net/paul0926/article/details/92761909
调试一下单个id查询,也就是查某个省级下所有的市级行政单位:
出现这种效果则成功。
省市区的数据是经常被用户查询使用的,而且数据基本不变化,所以我们可以将省市区数据进行缓存处理,减少数据库的查询次数。
查看官方文档:http://chibisov.github.io/drf-extensions/docs/#caching
先pip安装:
pip install drf-extensions
先导包然后给具体请求方法加装饰器
from rest_framework_extensions.cache.decorators import cache_response
class EmailVerifyView(APIView):
# 激活邮箱
@cache_response(timeout=60*60, cache='default')
def get(self, request, token):
有两个参数:
在自己的设置文件里添加即可:
# DRF扩展
REST_FRAMEWORK_EXTENSIONS = {
# 缓存时间
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
# 缓存存储
'DEFAULT_USE_CACHE': 'default',
}
drf-extensions扩展对于缓存提供了三个扩展类:
导包,类多继承一个即可
# 添加缓存
from rest_framework_extensions.cache.mixins import CacheResponseMixin
class AreasInfoView(ReadOnlyModelViewSet, CacheResponseMixin):
"""提供省市区三级联动数据"""