一.省市区地址查询
首先分析数据模型类的设计
设计成3张表肯定是不合理的,由于省,市,区具有共性,我们将其设置成一张表
id,name,parent
省的parent设置为null,市的parent设置为省的id,区(县)的parent设置为市的id
class Area(models.Model):
"""
行政区划
"""
name = models.CharField(max_length=20, verbose_name='名称')
parent = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='area_set', null=True, blank=True,
verbose_name='上级行政区划')
class Meta:
db_table = 'tb_areas'
verbose_name = '行政区划'
verbose_name_plural = '行政区划'
def __str__(self):
return self.name
完成数据迁移操作
python manage.py makemigrations
python manage.py migrate
向数据表中添加数据
1.直接复制.sql文件中的全部内容,粘贴到数据库中(终端)
2.在终端中使用source方式导入(需要注意.sql文件的路径)
3.脚本导入创建一个.sh文件(假设创建abc.sh)
#!/usr/bin/env bash
mysql -h127.0.0.1 -uname -ppassword databasename < ./file.sql
修改文件执行权限
chmod +x abc.sh
然后执行如下命令导入数据
./abc.sh
这样数据就全部添加到数据表中了
刷新页面时,获得所有省信息
选择省获取所有市信息
选择市获取所有区县信息
1)请求省份数据
请求方式 GET /areas/infos/
返回数据
返回值 | 类型 | 是否必传 | 说明 |
---|---|---|---|
id | int | 是 | 省份id |
name | str | 是 | 省份名称 |
2)请求城市或区县数据
请求方式 GET/areas/infos/(?P<pk>\d+)/
请求参数
参数 | 类型 | 是否必传 | 说明 |
---|---|---|---|
pk | int | 是 | 上级区划id(省份id用于获取城市数据,或城市id用于获取区县数据) |
返回数据
返回值 | 类型 | 是否必传 | 说明 |
---|---|---|---|
id | int | 是 | 上级区划id(省份id或城市id) |
name | str | 是 | 上级区划的名称 |
subs | list[] | 是 | 下属所有区划信息 |
可以知道以上都是get方法,我们可以使用ReadOnlyModelViewSet
class AreasViewSet(ReadOnlyModelViewSet):
pagination_class = None # 区划信息不分页
def get_queryset(self):
"""
提供数据集
"""
if self.action == 'list':
return Area.objects.filter(parent=None)
else:
return Area.objects.all()
# serializer_class = AreaSerializer
def get_serializer_class(self):
if self.action == 'list':
return AreaSerializer
else:
return SubAreaSerializer
代码分析:
由于省和市区的查询结果集是不相同的,所以我们需要重写get_queryset来重新定义结果集
if self.action == 'list':
return Area.objects.filter(parent=None)
这个很容易能够知道,查询的结果集就是数据表中parent=None的数据
else:
return Area.objects.all()
我们要知道市区是怎么实现的
ReadOnlyModelViewSet继承了RetrieveModelMixin,
RetrieveModelMixin有retrieve函数,get_object中实现了用PK值返回单个对象
所以直接 return Area.objects.all()就可以了
序列化器
class AreaSerializer(serializers.ModelSerializer):
"""
行政区划信息序列化器
"""
class Meta:
model = Area
fields = ['id', 'name', 'parent_id']
class SubAreaSerializer(serializers.ModelSerializer):
area_set = AreaSerializer(many=True,read_only=True)
class Meta:
model = Area
fields = ['area_set']
在点击省获取到所有市信息,我们只能得到省的id,但省的id是这个省所有市的parent_id,
所以,我们可以用1对多的方式来获得数据
我们可以给定一个字段等于序列化器,得到的就是所有市的信息了
从市得到区的过程同上,就不需要额外写了
改写前端代码
二.使用缓存
省市区的数据是经常被用户查询使用的,而且数据基本不变化,所以我们可以将省市区数据进行缓存处理,减少数据库的查询次数。
安装:pip install drf-extensions
为省市区视图添加缓存(添加CacheResponseMixin)
from rest_framework_extensions.cache.mixins import CacheResponseMixin
# Create your views here.
class AreaViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
"""
行政区划信息
list: GET /areas/
retrieve: GET /areas/(?P<pk>\d+)/
"""
在setting中添加配置
# DRF扩展
REST_FRAMEWORK_EXTENSIONS = {
# 缓存时间
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 60,
# 缓存存储
'DEFAULT_USE_CACHE': 'default',
}
三.户地址管理
1.增加地址
2.地址列表
3.删除地址
4.修改信息
5.设置默认地址
同讲义中内容一模一样
2点需要注意的地方....
1.创建序列化器AddressSerializer时 exclude 中is_delete需要删除
2.地址列表中前端代码需要写在钩子函数中(因为页面一刷新就需要显示)
我他么写完了需要提交的时候要重新登录什么都没了........
算了算了,生气伤身......
等我心情好了换种继承类写一次......
最后结果: