## 1.一级视图: APIView 封装了request和response ```python from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status # 封装状态码 class UserAPIView(APIView): def get(self, request): """ get请求: request.query_params.get(**) post/file/*: request.data.get(**) """ return Response([{'id': 1, 'name': 'xslee'}], status=status.HTTP_201_CREATED) ``` ## 2.二级视图: GenericAPIView 继承自APIView, 一般与Mixin类组合使用 ```python from rest_framework.generics import GenericAPIView class MView(GenericAPIView): queryset = Blog.objects.all() serializer_class = UserSerializer lookup_field = 'pk' def get(self, request, user_id): self.get_queryset() self.get_serializer() self.get_object() ``` ```python 三属性&&三方法: 1. queryset # 指定查询集 2. serializer_class # 指定序列化器 3. lookup_field # 模型字段名(pk/id), 源码中为pk 1. self.get_queryset() # 获取查询集 2. self.get_serializer(queryset, many=True) # 获取序列化器 3. self.get_object() # 只用在详情试图下获取当前user_id实例化对象, 由系统根据pk/id自动查找 """ lookup_field&&lookup_url_kwargs lookup_field 对应的指定的是模型类中用来查询的字段一般是pk/id lookup_field='pk/id' 指定根据User模型类的id查找 lookup_url_kwargs 对应的是url中的命名参数(方法参数) lookup_url_kwargs=user_id .../users/(?P<user_id>\d+)/$ def get(self, request, user_id) 方法参数user_id要与命名参数user_id保持一致, 由lookup_url_kwargs指定 """ class BlogsView(GenericAPIView): queryset = Blog.objects.all() serializer_class = BlogSerializer def get(self, request): blogs = self.get_queryset() serializer = self.get_serializer(blogs, many=True) serializer.data # 序列化后的数据 return Response({'status': status.HTTP_200_OK, 'blogs': serializer.data}) ``` ## 3.Mixin混合类: 配合GenericAPIView, 提供模型的LCURD通用功能 ```python from rest_framework.mixins import ListModelMixin from rest_framework.mixins import CreateModelMixin # 自定义保持规则, 重写perform_create(self, serializer)方法 from rest_framework.mixins import UpdateModelMixin # 自定义更新, 重写perform_update(self, serializer)方法 from rest_framework.mixins import RetrieveModelMixin # put->retrieve 获取单条数据 from rest_framework.mixins import DestroyModelMixin ``` ## 4.三级通用视图: 继承自GenericAPIView: LCURD+GenericAPIView # 不使用大量的自定义行为 ```python from rest_framework.generics import ListAPIView from rest_framework.generics import CreateAPIView from rest_framework.generics import UpdateAPIView from rest_framework.generics import RetrieveAPIView from rest_framework.generics import DestroyAPIView # LC+URD class GoodsSpuLCAPIView(ListCreateAPIView): authentication_classes = [LoginAuthentication, ] queryset = GoodsSpu.objects.order_by().all() serializer_class = GoodsSkuSerializer4Params pagination_class = ListPagination def get_queryset(self): query = self.request.query_params.get('query', '') if query: return self.queryset.filter(name__contains=query) return self.queryset class GoodsSpuRUDAPIView(RetrieveUpdateDestroyAPIView): authentication_classes = [LoginAuthentication, ] queryset = GoodsSpu.objects.all() serializer_class = GoodsSkuSerializer4Params lookup_field = 'pk' lookup_url_kwarg = 'goodsSpu_id' ``` ## 4.视图集: ```python from rest_framework.viewsets import ViewSet from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import ReadOnlyModelViewSet from rest_framework.viewsets import ModelViewSet # 在as_view()中, 指定方法与标准请求方式的映射 as_view({'get': 'list', 'post': 'create'.....}) 一般配合路由使用 ``` ```python 1. ViewSet 继承自APIView ``` 2. GenericViewSet 继承自GenericAPIView, 拥有三属性三方法, 自定义方法时, 在as_view中映射 3. ReadOnlyModelViewSet 继承自GenericViewSet + LRMixin 拥有三属性三方法, 不修改数据, 只用来获取数据 4. ModelViewSet 继承自GenericViewSet + LCURDMixin 5. 视图集的额外动作: partial # 允许前端传递模型部分字段数据用来更新 ser = self.get_serializer(..., partial=True) 前端可以只传递模型部分字段{'name': 'xs'} ```python # # authentications.py class LoginAuthentication(BaseAuthentication): """ 继承BaseAuthentication类,重写authenticate方法。 """ def authenticate(self, request): token = request.META.get('HTTP_AUTHORIZATION') try: user_token = UserToken.objects.get(token=token) except UserToken.DoesNotExist as e: raise exceptions.AuthenticationFailed("验证失败") return user_token.user, user_token # views中 request.user, request.auth = user_token.user, user_token def authenticate_header(self, request): pass # # pagination.py class UserListPagination(PageNumberPagination): page_query_param = 'pagenum' page_size_query_param = 'pagesize' max_page_size = 10 def get_paginated_response(self, data): return Response({ 'data': { 'count': self.page.paginator.count, # 数据总数 'users': data, # 当前页集 'page': self.page.number, # 第*页 'pages': self.page.paginator.num_pages, # 总页数 'pagesize': self.request.query_params.get('pagesize') or self.max_page_size, # 当前页数据量 # ('next', self.get_next_link()), # ('previous', self.get_previous_link()), }, 'meta': { 'status': status.HTTP_200_OK, 'msg': '获取用户成功' } }) # # serializers.py class UserSerializer(serializers.ModelSerializer): password = serializers.CharField(max_length=15, min_length=6, write_only=True) class Meta: model = Users fields = ('id', 'username', 'email', 'is_active', 'password') extra_kwargs = { """'username': { 'read_only': True, }""" } def validated_password(self, value): if 6 <= len(value) <= 15: return value raise serializers.ValidationError(u"密码长度不合法, 密码6-15位") def create(self, validated_data): user = Users.objects.create( username=validated_data.get('username'), email=validated_data.get('email'), ) user.set_password(validated_data.get('password')) user.save() return user def update(self, instance, validated_data): instance.is_active = validated_data.get('is_active') instance.email = validated_data.get('email') instance.set_password(validated_data.get('password')) instance.save() return instance # # views.py class UserListAPIView(ListAPIView): authentication_classes = [LoginAuthentication] pagination_class = UserListPagination serializer_class = UserSerializer queryset = Users.objects.filter(is_superuser=0).order_by('id').all() def get_queryset(self): query = self.request.query_params.get('query') if not query: return self.queryset return Users.objects.filter(username__contains=query).order_by('id').all() # # urls.py url(r'^users/', views.UserListAPIView.as_view(), name='users') /bk/users/?query=xs&pagenum=1&pagesize=2 /bk/users/?query=&pagenum=1&pagesize=2 ```
浙公网安备 33010602011771号