通用视图的继承关系
安装DRF
pip install djangorestframework
在settings中注册
INSTALLED_APPS = [
'rest_framework',
]
一.序列化器(针对模型类)
(1).通过继承rest_framework.serializers.Serializer来定义序列化器;定义和模型类的定义类似,不过模型类的字段models.IntegerField(),而序列化器为serializers.IntegerField()
(2).通过继承serializers.ModelSerializer,那么字段都不用定义了,通过元类Meta指定模型类:
所有:
class Meta:
# 1. 返回关联对象的主键
department = PrimaryKeyRelatedField(read_only=True)
model = Department # 指定模型类
fields = '__all__' # 指定要序列化哪些栏位(可以是模型类中的字段,也可以模型类中没有的但需要校验的属性(加上write_only=True),比如:短信验证码,确认密码)
read_only_fields = ('id', 'create_date') # 这些字段不能修改
extra_kwargs = {
'name': {'min_length': 5, 'max_length': 20},
'age': {'min_value': 1, 'max_value': 200},
}
指定(元组):
class DepartmentSerializer2(serializers.ModelSerializer):
class Meta:
model = Department
fields = ('id', 'name')
排除:
class DepartmentSerializer2(serializers.ModelSerializer):
class Meta:
model = Department
exclude = ('is_delete',)
二.序列化的使用(传入对象为序列化)
(1).基本使用(list、retrieve)
传入模型类对象(如果要序列化的是包含多条数据的QuerySet,则需要指定many=True)来创建模型化器对象(serializer)-->通过data属性获得序列化后的结果(serializer.data)
(2).关联对象序列化(多个对象加入many=True)
第1种:返回关联对象的主键(必须包含read_only=True或者queryset参数)
在序列化器中加入:department = serializers.PrimaryKeyRelatedField(label='所属部门', read_only=True)
第2种:返回关联对象的 字符串表示方式,即__str__方法的返回值
在序列化器中加入:department = serializers.StringRelatedField(label='所属部门')
第3种:返回关联对象序列化器定义的所有属性
在对应序列化器中加入一个新的序列化器(包含要显示的字段):department = DepartmentSerializer(label='所属部门')
三.反序列化的使用(传入request.data为反序列化)
(1).通过调用is_valid(raise_exception=True)方法,自动调用检验方法校验传入的数据;
(2).error属性:获取校验出错信息,字典类型;
(3).validated_data属性:校验通过得到的对象,为OrderedDict类型.
四.参数校验的集中方式(序列化器对象.is_valid()自动调用)
(1).通过写在序列化器中定义validate_字段名:对单个字段进行校验,def validate_name(self, value)自动会将name字段传入value接收
(2).validate:同时对多个字段进行比较验证,def validate(self, attrs)自动会将序列化器中fields中的字段以字典的形式传入由attrs接收
五.保存或修改数据(save(),create(),update())
(1).新增(只传入了data数据)
my_dict = {'name': '研发部xx', 'create_date': '2018-1-1'}
s = DepartmentSerializer(data=my_dict)
s.save()
(2).修改(同时传入了模型类对象和data)
department = Department.objects.get(id=1)
my_dict = {'name': '研发部xx', 'create_date': '2018-1-1'}
s = DepartmentSerializer(instance=department, data=my_dict)
s.save()
(3).部分修改:传入partial=True
(4).继承serializers.Serializer需要重写create和update方法(都要返回创建或修改好的对象)
五.视图(调用序列化器不需要传入参数,除了APIView要传入对应参数外,其他只要指定就好序列化器、查询集)
"""
1.校验函数的调用也封装了(Minxin)
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
2. 增加对象只需要指定序列化器就可以了,除了APIView其他指定序列化器都不需要传入参数
3.GenericAPIView只提供了属性(queryset、serializer_class)和方法(get_queryset(self)、get_serializer_class(self)),操作基本都有xxxModelMixin提供
"""
DRT用Response,Request;
request.data相当于request.POST, request.body和request.FILES组合;
request.query_params相当于request.GET
(1).APIView(和view类似,在类视图中根据请求方式定义不同的方法,传入参数进行处理)
(2).GenericAPIView(通常与五个扩展类结合使用)
提供的关于序列化器使用的属性与方法
1.serializer_class指明要使用的序列化器.
2.get_serializer_class()返回序列化器类,默认返回serializer_class.
3.get_serializer()获取序列化器对象
4.queryset指明使用的数据查询集.
5.get_queryset()返回查询集,默认返回queryset.
6.get_object()根据pk来获取模型类对象
六.GenericAPIView与五个扩展类的组合
ListModelMixin(list)
CreateModelMixin(create)
RetrieveModelMixin(retrieve)
UpdateModelMixin(update)
DestroyModelMixin(destroy)
继承相应的扩展类和GenericAPIView,在方法外面指定数据集和序列化器,返回相应的方法
class DepartmentListAPIView2(ListModelMixin, CreateModelMixin, GenericAPIView):
queryset = Department.objects.all()
serializer_class = DepartmentSerializer
def get(self, request):
# 调用ListModelMixin的方法,查询多条数据
return self.list(request)
七.其他子类视图
CreateAPIView
ListAPIView
RetrieveAPIView
DestroyAPIView
UpdateAPIView
继承相应的子类视图,只需指定查询集和序列化器就可以完成基本的增删改查
八.视图集(将同一种查询方式放在同一个视图中):
(1).继承viewsets.ViewSet,定义list,retrieve方法
(2).继承GenericViewSet和五个扩展类其中一部分:
1.视图类继承GenericViewSet和对应的扩展类,视图类中只需要指定queryset和serializer_class;
2.自定义action方法:
def latest(self, request):
"""
自定义action: 查询最新成立的部门
"""
department = Department.objects.latest('create_date')
serializer = self.get_serializer(department)
return Response(serializer.data)
def name(self, request, pk):
"""
自定义action: 修改部门名称
"""
dep = self.get_object()
dep.name = request.data.get('name')
dep.save()
serializer = self.get_serializer(dep)
return Response(serializer.data)
请求方式还是那些
(3).继承ModelViewSet默认实现五个接口
(4).视图集定义路由:
router = SimpleRouter()
# 参数1: 路由访问的前缀
# 参数2: 视图集
# 参数3: 路由名称的前缀, 可以不指定
# ^departments/$ name: dep-list
router.register(r'depart2', MyDepartmentViewSet2, base_name='dep') # 需要pk会默认传入
router.register(r'employee5', MyEmployeeViewSet, base_name='emp') # 需要pk会默认传入
urlpatterns += router.urls
需要为自定义action方法添加一个装饰器 @action(methods=['get'], detail=False)detail声明该action的路径是否与单一资源对应,才会自动生成路由:前缀/action方法名/