一、Django CBV 调用流程
r'^login/', views.LoginView.as_view() r'^login/', views.as_view() r'^login/', views.view() class View(object): http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def view(request, *args, **kwargs): self = cls(**initkwargs) return self.dispatch(request, *args, **kwargs) def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) from django.views import View class LoginView(View): def get(self, request): return render(request, 'login.html') def post(self, request): user = request.POST.get('user') pwd = request.POST.get('pwd') if user == 'zane' and pwd == '123': return HttpResponse('用户 %s 登陆成功!' % user) else: return HttpResponse('用户名或密码错误!')
二、Django RestFramework 调用流程
r'^teachers/', views.TeacherView.as_view() r'^teachers/', APIView.as_view() r'^teachers/', View.view() class View(object): http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def view(request, *args, **kwargs): self = cls(**initkwargs) # 此时返回的是 APIView.dispatch(request, *args, **kwargs) return self.dispatch(request, *args, **kwargs) def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) class APIView(View): def as_view(cls, **initkwargs): view = super(APIView, cls).as_view(**initkwargs) return csrf_exempt(view) def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) return self.response from rest_framework.views import APIView from django.core.serializers import serialize class TeacherView(APIView): def get(self, request): teachers = Teacher.objects.all() teachers = serialize('json', teachers) return HttpResponse(teachers) def post(self, request): return HttpResponse('OK')
三、Django 序列化
r'^courses/', views.CourseView.as_view() from django.views import View class CourseView(View): def get(self, request): # 1. json 序列化 # import json # courses = Course.objects.all() # tmp = [] # for course in courses: # tmp.append({"name": course.name}) # courses = json.dumps(tmp, ensure_ascii=False) # 2. Django 自带序列化组件 from django.core.serializers import serialize courses = Course.objects.all() courses = serialize('json', courses) return HttpResponse(courses) def post(self, request): return HttpResponse('ok')
四、Django RestFramework 序列化
r'^course_detail/', views.CourseDetailView.as_view() from rest_framework import serializers class CourseDetailSerializer(serializers.Serializer): # 一对一、一对多字段,使用 source 参数获取序列化字段 course = serializers.CharField(source='course.name') # 多对多字段,使用 SerializerMethodField 并指定 get_teachers 方法获取序列化字段 teachers = serializers.SerializerMethodField() def get_teachers(self, obj): tmp = [] for o in obj.teachers.all(): tmp.append(o.name) teachers = ','.join(tmp) return teachers from rest_framework.views import APIView from rest_framework.response import Response class CourseDetailView(APIView): def get(self, request): # Django Restframework 序列化 course_details = CourseDetail.objects.all() course_detail_serializer_obj = CourseDetailSerializer(course_details, many=True) return Response(course_detail_serializer_obj.data) def post(self, request): return HttpResponse('ok')
from rest_framework import serializers from api.models import UserToken class UserTokenSerializer(serializers.ModelSerializer): # 覆盖并自定义序列化字段(一对一、一对多、多对多都可以覆盖自定义) user = serializers.CharField(source='user.user') class Meta: model = UserToken fields = '__all__' from rest_framework.views import APIView from api.serializers import UserTokenSerializer from rest_framework.response import Response class UserTokenView(APIView): def get(self, request): # Django Restframework 序列化 user_tokens = UserToken.objects.all() user_token_serializer_obj = UserTokenSerializer(user_tokens, many=True) return Response(user_token_serializer_obj.data) def post(self, request): return HttpResponse('ok')
五、Django Restframework 视图
from rest_framework import serializers from api.models import UserToken class UserTokenSerializer(serializers.ModelSerializer): user = serializers.CharField(source='user.user') token = serializers.CharField() def create(self, validated_data): user = int(validated_data.get('user').get('user')) token = validated_data.get('token') user_obj = User.objects.get(pk=user) user_token_obj = UserToken.objects.create(user=user_obj, token=token) return user_token_obj class Meta: model = UserToken # fields = '__all__' exclude = ['id'] from rest_framework.views import APIView from api.serializers import UserTokenSerializer from rest_framework.response import Response class UserTokenView(APIView): def get(self, request): # Django Restframework 序列化 user_tokens = UserToken.objects.all() user_token_serializer_obj = UserTokenSerializer(user_tokens, many=True) return Response(user_token_serializer_obj.data) def post(self, request): ret = { 'status': 200, 'message': '创建UserToken成功!' } print(request.data) user_token_serializer_obj = UserTokenSerializer(data=request.data) if user_token_serializer_obj.is_valid(): user_token_serializer_obj.save() else: ret['status'] = 2001 ret['message'] = user_token_serializer_obj.errors return Response(ret) class UserTokenDetailView(APIView): def get(self, request, pk): user_token = UserToken.objects.filter(pk=pk).first() user_token_serializer_obj = UserTokenSerializer(user_token, many=False) return Response(user_token_serializer_obj.data) def put(self, request, pk): ret = { 'status': 200, 'message': '更新UserToken成功!' } user_token = UserToken.objects.filter(pk=pk).update(token=request.data.get('token')) if not user_token: ret['status'] = 2001 ret['message'] = '更新UserToken失败!' return Response(ret) def delete(self, request, pk): ret = { 'status': 200, 'message': '删除UserToken成功!' } if not UserToken.objects.filter(pk=pk).delete(): ret['status'] = 2002 ret['message'] = '删除UserToken失败!' return Response(ret)
from rest_framework import serializers from api.models import User class UserSerializer(serializers.Serializer): user = serializers.CharField() type = serializers.CharField() bely = serializers.IntegerField() def create(self, validated_data): user_obj = User.objects.create(**validated_data) return user_obj # 方法1 使用 ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, generics.GenericAPIView 类 from rest_framework.mixins import ListModelMixin, CreateModelMixin from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin from rest_framework import generics class UserView(ListModelMixin, CreateModelMixin, generics.GenericAPIView): queryset = User.objects.all() serializer_class = UserSerializer def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) class UserDetailView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, generics.GenericAPIView): queryset = User.objects.all() serializer_class = UserSerializer def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.update(request, *args, **kwargs) def delete(self, request, *args, **kwargs): return self.destroy(request, *args, **kwargs) # 方法2 使用 ListCreateAPIView 和 RetrieveUpdateDestroyAPIView 类 from rest_framework import generics class UserView(generics.ListCreateAPIView): queryset = User.objects.all() serializer_class = UserSerializer class UserDetailView(generics.RetrieveUpdateDestroyAPIView): queryset = User.objects.all() serializer_class = UserSerializer
# 路由配置 r'^users/$', views.UserModelView.as_view({'get': 'list', 'post': 'create'}) r'^users/(?P<pk>d+)/$', views.UserModelView.as_view({'get': 'retrieve', 'post': 'update'}) # 序列化类 from rest_framework import serializers from api.models import User class UserSerializer(serializers.Serializer): user = serializers.CharField() type = serializers.CharField() bely = serializers.IntegerField() def create(self, validated_data): user_obj = User.objects.create(**validated_data) return user_obj # 视图使用已经混合好的 ModelViewSet 类 from rest_framework.viewsets import ModelViewSet class UserModelView(ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer
from django.shortcuts import get_object_or_404 as _get_object_or_404 # 补充:第5步 调用get_object_or_404 方法,实际调用 django.shortcuts 导入的 get_object_or_404 方法 def get_object_or_404(queryset, *filter_args, **filter_kwargs): return _get_object_or_404(queryset, *filter_args, **filter_kwargs) # 补充:第5步 实际的 django.shortcuts.get_object_or_404 被调用 def get_object_or_404(klass, *args, **kwargs): return queryset.get(*args, **kwargs) class GenericAPIView(views.APIView): lookup_field = 'pk' lookup_url_kwarg = None def get_queryset(self): # 2. 获取视图类的 queryset 属性 queryset = self.queryset if isinstance(queryset, QuerySet): queryset = queryset.all() return queryset def get_object(self): # 1. 获取并过滤视图类的 queryset 属性 queryset = self.filter_queryset(self.get_queryset()) # 3. 查询过滤键名 lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field # 4. 过滤参数(定义成字典) filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]} # 5. 传入过滤参数进行过滤,调用上面的 get_object_or_404 方法 obj = get_object_or_404(queryset, **filter_kwargs) return obj # 补充:第3步 self.kwargs 来自调用视图时传入的参数 class ViewSetMixin(object): def as_view(cls, actions=None, **initkwargs): def view(request, *args, **kwargs): self.request = request self.args = args self.kwargs = kwargs
六、Django Restframework 解析器
# Django Restframework 解析器调用流程 # 1. 使用视图类单独配置 from rest_framework.parsers import JSONParser, FormParser, MultiPartParser class UserModelView(ModelViewSet): parser_classes = [JSONParser, FormParser, MultiPartParser] # 2. 使用settings全局配置 # settings 全局配置 REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ) } # 3. 如果settings没有配置,则使用 api_settings 的默认配置 DEFAULTS = { 'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ) } # 源码调用流程 class APIView(View): # 视图类没有 self.parser_classes 属性时调用 parser_classes = api_settings.DEFAULT_PARSER_CLASSES def get_parsers(self): # 1. 获取视图类单独配置 return [parser() for parser in self.parser_classes] def initialize_request(self, request, *args, **kwargs): return Request( request, # 获取解析器 parsers=self.get_parsers(), authenticators=self.get_authenticators(), negotiator=self.get_content_negotiator(), parser_context=parser_context ) def dispatch(self, request, *args, **kwargs): # 从初始化request开始调用流程 request = self.initialize_request(request, *args, **kwargs) # 当视图类没有 self.parser_classes 属性时调用 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS) class APISettings(object): # 获取 settings 全局配置 @property def user_settings(self): if not hasattr(self, '_user_settings'): self._user_settings = getattr(settings, 'REST_FRAMEWORK', {}) return self._user_settings def __getattr__(self, attr): try: # 2. 获取 settings 全局配置 val = self.user_settings[attr] except KeyError: # 3. 获取 api_settings 默认配置 val = self.defaults[attr] setattr(self, attr, val) return val