Django中views笔记

reverse反解析

1 #路由中定义namespace、name,reverse可将其转换为url
2 url = reverse('namespace:name')
3 return redirect(url)
View Code

HttpRequest对象

1.路径参数

  位置参数
  • 应用中urls.py

     url(r'^(\d+)/(\d+)/$', views.index),
  • 视图中函数: 参数的位置不能错

    def index(request, value1, value2):
          # 构造上下文
          context = {'v1':value1, 'v2':value2}
          return render(request, 'Book/index.html', context)
  关键字参数
  • 应用中urls.py

    • 其中?P<value1>部分表示为这个参数定义的名称为value1
    • 可以是其它名称,起名要做到见名知意

      url(r'^(?P<value1>\d+)/(?P<value2>\d+)/$', views.index),
  • 视图中函数: 参数的位置可以变,跟关键字保持一致即可

    def index(request, value2, value1):
          # 构造上下文
          context = {'v1':value1, 'v2':value2}
          return render(request, 'Book/index.html', context)

2.查询字符串Query String

  获取请求路径中的查询字符串参数(形如?k1=v1&k2=v2),可以通过request.GET属性获取,返回QueryDict对象。

 1 # /get/?a=1&b=2&a=3
 2 
 3 def get(request):
 4     a = request.GET.get('a')
 5     b = request.GET.get('b')
 6     alist = request.GET.getlist('a')
 7     print(a)  # 3
 8     print(b)  # 2
 9     print(alist)  # ['1', '3']
10     return HttpResponse('OK')
View Code

3.表单类型 Form Data

前端发送的表单类型的请求体数据,可以通过request.POST属性获取,返回QueryDict对象。

1 def post(request):
2     a = request.POST.get('a')
3     b = request.POST.get('b')
4     alist = request.POST.getlist('a')
5     print(a)
6     print(b)
7     print(alist)
8     return HttpResponse('OK')
View Code

4.非表单类型 Non-Form Data

非表单类型的请求体数据,Django无法自动解析,可以通过request.body属性获取最原始的请求体数据,自己按照请求体格式(JSON、XML等)进行解析。request.body返回bytes类型。

例如要获取请求体中的如下JSON数据

{"a": 1, "b": 2}

可以进行如下方法操作:

1 import json
2 
3 def post_json(request):
4     json_str = request.body
5     json_str = json_str.decode()  # python3.6 无需执行此步
6     req_data = json.loads(json_str)
7     print(req_data['a'])
8     print(req_data['b'])
9     return HttpResponse('OK')
View Code

5.请求头

可以通过request.META属性获取请求头headers中的数据,request.META为字典类型。

常见的请求头如:

  • CONTENT_LENGTH– The length of the request body (as a string).
  • CONTENT_TYPE– The MIME type of the request body.
  • HTTP_ACCEPT– Acceptable content types for the response.
  • HTTP_ACCEPT_ENCODING– Acceptable encodings for the response.
  • HTTP_ACCEPT_LANGUAGE– Acceptable languages for the response.
  • HTTP_HOST– The HTTP Host header sent by the client.
  • HTTP_REFERER– The referring page, if any.
  • HTTP_USER_AGENT– The client’s user-agent string.
  • QUERY_STRING– The query string, as a single (unparsed) string.
  • REMOTE_ADDR– The IP address of the client.
  • REMOTE_HOST– The hostname of the client.
  • REMOTE_USER– The user authenticated by the Web server, if any.
  • REQUEST_METHOD– A string such as"GET"or"POST".
  • SERVER_NAME– The hostname of the server.
  • SERVER_PORT– The port of the server (as a string).

具体使用如:

def get_headers(request):
    print(request.META['CONTENT_TYPE'])
    return HttpResponse('OK')

6.其他常用HttpRequest对象属性

  • method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。
  • user:请求的用户对象。
  • path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。
  • encoding:一个字符串,表示提交的数据的编码方式。

    • 如果为None则表示使用浏览器的默认设置,一般为utf-8。
    • 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值。
  • FILES:一个类似于字典的对象,包含所有的上传文件。

HttpResponse对象

1 HttpResponse

可以使用django.http.HttpResponse来构造响应对象。

HttpResponse(content=响应体, content_type=响应体数据类型, status=状态码)
1 from django.http import HttpResponse
2 
3 def response(request):
4     return HttpResponse('itcast python', status=400)
5     或者
6     response = HttpResponse('itcast python')
7     response.status_code = 400
8     response['itcast'] = 'Python'
9     return response
View Code

2 HttpResponse子类

Django提供了一系列HttpResponse的子类,可以快速设置状态码

  • HttpResponseRedirect 301
  • HttpResponsePermanentRedirect 302
  • HttpResponseNotModified 304
  • HttpResponseBadRequest 400
  • HttpResponseNotFound 404
  • HttpResponseForbidden 403
  • HttpResponseNotAllowed 405
  • HttpResponseGone 410
  • HttpResponseServerError 500

3 JsonResponse

若要返回json数据,可以使用JsonResponse来构造响应对象,作用:

  • 帮助我们将数据转换为json字符串
  • 设置响应头Content-Type为application/json
1 from django.http import JsonResponse
2 
3 def response(request):
4     return JsonResponse({'city': 'beijing', 'subject': 'python'})
View Code

4 redirect重定向

1 from django.shortcuts import redirect
2 
3 def response(request):
4     return redirect('/get_header')
View Code

cookie和session

示例代码:

 1 def set_cookie(request):
 2     '''设置cookie'''
 3     name=request.GET.get('name')
 4     pwd=request.GET.get('pwd')
 5     response=HttpResponse('set cookie')
 6     response.set_cookie('name',name)
 7     response.set_cookie('pwd',pwd,max_age=60)
 8     return response
 9 
10 def get_cookie(request):
11     '''获取cookie'''
12     name=request.COOKIES.get('name')
13     pwd=request.COOKIES.get('pwd')
14     return HttpResponse("name:%s,pwd:%s"%(name,pwd))
15 
16 def del_cookie(request):
17     '''删除cookie'''
18     response=HttpResponse('del cookie')
19     response.delete_cookie('name')
20     return response
21 
22 def to_session(request):
23     '''session操作'''
24     name=request.COOKIES.get('name')
25     # 1) 以键值对的格式写session。
26     request.session['name']=name
27     # 2)根据键读取值。
28     session_name=request.session.get('name')
29     return HttpResponse('%s'%session_name)
30     # 3)清除所有session,在存储中删除值部分。
31     request.session.clear()
32     # 4)清除session数据,在存储中删除session的整条数据。
33     request.session.flush()
34     # 5)删除session中的指定键及值,在存储中只删除某个键及对应的值。
35     del request.session['name']
36     # 6)设置session的有效期单位秒
37     request.session.set_expiry(60)
View Code

中间件 

1 .中间件的定义方法

定义一个中间件工厂函数,然后返回一个可以被调用的中间件。

中间件工厂函数需要接收一个可以调用的get_response对象。

返回的中间件也是一个可以被调用的对象,并且像视图一样需要接收一个request对象参数,返回一个response对象。

 1 def simple_middleware(get_response):
 2     # 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。
 3 
 4     def middleware(request):
 5         # 此处编写的代码会在每个请求处理视图前被调用。
 6 
 7         response = get_response(request)
 8 
 9         # 此处编写的代码会在每个请求处理视图之后被调用。
10 
11         return response
12 
13     return middleware
示例代码

2.例如,在book应用中新建一个middleware.py文件

1 def my_middleware(get_response):
2     print('init 被调用')
3     def middleware(request):
4         print('before request 被调用')
5         response = get_response(request)
6         print('after response 被调用')
7         return response
8     return middleware
View Code

3.定义好中间件后,需要在settings.py 文件中添加注册中间件

 1 MIDDLEWARE = [
 2     'django.middleware.security.SecurityMiddleware',
 3     'django.contrib.sessions.middleware.SessionMiddleware',
 4     'django.middleware.common.CommonMiddleware',
 5     # 'django.middleware.csrf.CsrfViewMiddleware',
 6     'django.contrib.auth.middleware.AuthenticationMiddleware',
 7     'django.contrib.messages.middleware.MessageMiddleware',
 8     'django.middleware.clickjacking.XFrameOptionsMiddleware',
 9     'book.middleware.my_middleware',  # 添加中间件
10 ]
View Code

rest_framework实现序列化器

1.配置文件setting

INSTALLED_APPS = [
    'rest_framework'
]

2.创建序列化器文件 serializers.py

  方式一继承Serializer

 1 from rest_framework import serializers
 2 
 3 from book.models import BookInfo
 4 
 5 
 6 class BookInfoSerializer(serializers.Serializer):
 7     '''书籍数据序列化'''
 8 
 9     def custom_validate(value):
10         if value == 'hehe':
11             raise serializers.ValidationError('书名不能为hehe')
12 
13     id = serializers.IntegerField(label='id', read_only=True)
14     name = serializers.CharField(label='书名', max_length=20, validators=[custom_validate])  # validators为自定义限定函数集
15     click_count = serializers.IntegerField(label='点击量', required=False)
16     scan_count = serializers.IntegerField(label='浏览量', required=False)
17     image = serializers.ImageField(label='封面', required=False)
18     create_time = serializers.DateTimeField(label='创建时间', required=False)
19     peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
20 
21     def validate_click_count(self, value):  # 指定字段限定条件,命名方式为validate_字段名,接收字段值value
22         if value < 0:
23             raise serializers.ValidationError('点击量不能小于0')
24         return value
25 
26     def validate_scan_count(self, value):
27         if value < 0:
28             raise serializers.ValidationError('浏览量不能小于0')
29         return value
30 
31     def validate(self, attrs): # 多个字段限定条件,固定函数名validate,传入字典字段值attrs
32         click_count = attrs.get('click_count')
33         scan_count = attrs.get('scan_count')
34         if click_count > scan_count:
35             raise serializers.ValidationError('浏览量不能小于点击量')
36         return attrs
37 
38     def create(self, validated_data):
39         '''新增数据'''
40         return BookInfo.objects.create(**validated_data)
41 
42     def update(self, instance, validated_data):
43         '''更新数据'''
44         instance.name = validated_data.get('name', instance.name)
45         instance.click_count = validated_data.get('click_count', instance.click_count)
46         instance.scan_count = validated_data.get('scan_count', instance.scan_count)
47         instance.create_time = validated_data.get('create_time', instance.create_time)
48         instance.save()
49         return instance
View Code

  方式二继承ModelSerializer

 1 from rest_framework import serializers
 2 
 3 from book.models import BookInfo
 4 
 5 
 6 class BookInfoSerializers(serializers.ModelSerializer):
 7     class Meta:
 8         model = BookInfo
 9         # fields='__all__' #取所有字段
10         # fields=['id','name','click_count'] # 取该字典中的字段
11         exclude = ['image']  # 取除了该字段的其他字段
12         read_only_fields = ['id', 'click_count', 'scan_count']  # 只读字段
13         # 字段限定条件
14         extra_kwargs = {
15             'click_count': {'min_value': 0, 'required': True},
16             'scan_count': {'min_value': 0, 'required': True}
17         }
View Code

rest_framework实现三个级别view

1.setting中增加如下:

1 REST_FRAMEWORK = {
2     'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
3         'rest_framework.renderers.JSONRenderer',  # json渲染器
4         'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
5     )
6 }
View Code

2. 一级视图 继承类 from rest_framework.views import APIView

 1 # 一级视图 继承类 from rest_framework.views import APIView
 2 from django.shortcuts import render
 3 from rest_framework.response import Response
 4 from rest_framework import status
 5 from rest_framework.views import APIView
 6 from book.models import BookInfo
 7 from book.serializers import BookInfoModelSerializer
 8 
 9 
10 class BookListView(APIView):
11     def get(self, request):
12         books = BookInfo.objects.all() #获取BookInfo模型所有数据
13         serializer = BookInfoModelSerializer(books, many=True) #初始化BookInfoModelSerializer序列化器
14         return Response(serializer.data) #返回数据
15 
16     def post(self, request):
17         data = request.data #获取请求数据
18         serializer = BookInfoModelSerializer(data=data) #初始化BookInfoModelSerializer序列化器
19         serializer.is_valid(raise_exception=True)#校验请求的数据,如果有异常抛出异常
20         serializer.save()# 保存操作
21         return Response(serializer.data)#返回数据
22 
23 
24 class BookDetailView(APIView):
25     def get(self, request, id):
26         book = BookInfo.objects.get(id=id) #查询模型BookInfo中指定数据
27         serializer = BookInfoModelSerializer(book) #初始化BookInfoModelSerializer序列化器
28         return Response(serializer.data) #返回数据
29 
30     def put(self, request, id):
31         book = BookInfo.objects.get(id=id)#查询模型BookInfo中指定数据
32         data = request.data# 获取请求数据
33         serializer = BookInfoModelSerializer(book, data=data)#初始化BookInfoModelSerializer序列化器
34         serializer.is_valid(raise_exception=True) #校验数据,如异常抛出
35         serializer.save() #保存数据
36         return Response(serializer.data)#返回数据
37 
38     def delete(self, request, id):
39         book = BookInfo.objects.get(id=id)# 查询模型BookInfo中指定数据
40         book.delete()# 删除数据
41         return Response(status=status.HTTP_204_NO_CONTENT)#返回状态
View Code
1 urlpatterns=[
2     # 一级视图 继承类 from rest_framework.views import APIView
3     url(r'^booklist/$',views.BookListView.as_view(),name='booklist'),
4     url(r'^bookdetail/(?P<id>\d+)$',views.BookDetailView.as_view(),name='bookdetail'),
5 ]
urls Code

3. 二级视图 继承类 from rest_framework.generics import GenericAPIView

 1 # 二级视图 继承类 from rest_framework.generics import GenericAPIView
 2 from rest_framework.generics import GenericAPIView
 3 from book.models import BookInfo
 4 from book.serializers import BookInfoModelSerializer
 5 from rest_framework.response import Response
 6 
 7 
 8 class BookListGenericAPIView(GenericAPIView):
 9     queryset = BookInfo.objects.all()# 获取所有数据赋值给queryset
10     serializer_class = BookInfoModelSerializer #初始化序列化器属性
11 
12     def get(self, request):
13         books = self.get_queryset()  # 通过父类方法获取queryset
14         serializer = self.get_serializer(books, many=True)  # 通过父类方法获取serializer_class
15         return Response(serializer.data) #返回数据
16 
17     def post(self, request):
18         data = request.data #获取请求数据
19         serializer = self.get_serializer(data=data)
20         serializer.is_valid(raise_exception=True)#校验数据,如异常抛出
21         serializer.save()#保存数据
22         return Response(serializer.data)#返回数据
23 
24 
25 class BookDetailGenericAPIView(GenericAPIView):
26     queryset = BookInfo.objects.all()# 获取所有数据赋值给queryset
27     serializer_class = BookInfoModelSerializer#初始化序列化器属性
28     # lookup_field = 'pk' #默认参数为pk
29     lookup_field = 'id'  # 可重写父类属性
30 
31     def get(self, request, id):
32         book = self.get_object()#通过父类方法获取模型中指定数据
33         serializer = self.get_serializer(book)# 通过父类方法获取序列化器
34         return Response(serializer.data)#返回数据
35 
36     def put(self, request, id):
37         book = self.get_object()
38         serializer = self.get_serializer(instance=book, data=request.data)
39         serializer.is_valid(raise_exception=True)
40         serializer.save()
41         return Response(serializer.data)#返回数据
42 
43     def delete(self, request, id):
44         book = self.get_object()
45         book.delete()
46         return Response(status=status.HTTP_204_NO_CONTENT)#返回状态
View Code
1 urlpatterns=[
2     # 二级视图 继承类 from rest_framework.generics import GenericAPIView
3     url(r'^booklistgeneric/$', views.BookListGenericAPIView.as_view(), name='booklistgeneric'),
4     url(r'^bookdetailgeneric/(?P<id>\d+)$', views.BookDetailGenericAPIView.as_view(), name='bookdetailgeneric'),
5 ]
urls Code

3.1. 二级视图和Mixin配合使用,Mixin中已经封装了get、post、get、put、delete相应功能,对应方法list、create、retrieve、update、destroy

 1 # 二级视图和Mixin配合使用,Mixin中已经封装了get、post、get、put、delete相应功能,对应方法list、create、retrieve、update、destroy
 2 from rest_framework.mixins import ListModelMixin, CreateModelMixin
 3 from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
 4 from rest_framework.generics import GenericAPIView
 5 
 6 
 7 class BookListMixinGenericAPIView(ListModelMixin, CreateModelMixin, GenericAPIView):
 8     # queryset = BookInfo.objects.all()
 9     # serializer_class = BookInfoModelSerializer
10     # 重写父类方法,获取数据
11     def get_queryset(self):
12         return BookInfo.objects.all()
13 
14     # 重写父类方法,设置序列化器
15     def get_serializer_class(self):
16         return BookInfoModelSerializer
17 
18     def get(self, request):
19         return self.list(request)
20 
21     def post(self, request):
22         return self.create(request)
23 
24 
25 class BookDetailMixinGenericAPIView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
26     # 获取所有数据赋值给queryset
27     queryset = BookInfo.objects.all()
28     # 设置序列化器属性
29     serializer_class = BookInfoModelSerializer
30 
31     def get(self, request, pk):
32         return self.retrieve(request)
33 
34     def put(self, request, pk):
35         return self.update(request)
36 
37     def delete(self, request, pk):
38         return self.destroy(request)
View Code
urlpatterns=[
    # 二级视图和Mixin配合使用
    url(r'^booklistmixingeneric/$', views.BookListMixinGenericAPIView.as_view(), name='booklistmixingeneric'),
    url(r'^bookdetailmixingeneric/(?P<pk>\d+)$', views.BookDetailMixinGenericAPIView.as_view(), name='bookdetailmixingeneric'),

]
urls Code

4.三级视图,高度封装

 1   
 2 # 三级视图,高度封装
 3 from rest_framework.generics import CreateAPIView,ListAPIView
 4 class BookListAPIView(ListAPIView,CreateAPIView):
 5     queryset = BookInfo.objects.all()
 6     serializer_class = BookInfoModelSerializer
 7 
 8 
 9 from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
10 class DetailAPIView(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
11     queryset = BookInfo.objects.all()
12     serializer_class = BookInfoModelSerializer
13 
14 from rest_framework.generics import RetrieveDestroyAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView
View Code
1 urlpatterns=[
2     # 三级视图
3     url(r'^booklistapiview/$', views.BookListAPIView.as_view(), name='booklistapiview'),
4     url(r'^detailapiview/(?P<pk>\d+)$', views.DetailAPIView.as_view(), name='detailapiview'),
5 
6 ]
urls Code

5.视图集ViewSet、ModelViewSet、ReadOnlyModelViewSet

 1 ##################################视图集 ##########################################
 2 
 3 """
 4 1. 有相同的相关业务逻辑 (对一个模型的 增删改查的操作)
 5 2. 列表试图和详情视图中 有重复的属性
 6 
 7 我们想到把 增删改查 放到一个视图中
 8 class Index(View):
 9 
10     def list()              get
11         pass
12 
13     def retrieve()          get
14         pass
15 
16 """
17 from rest_framework.viewsets import ViewSet
18 
19 
20 from rest_framework.viewsets import ViewSet
21 from django.shortcuts import get_object_or_404
22 from rest_framework.response import Response
23 
24 class BookViewSet(ViewSet):
25 
26     def list(self,request):                 # 获取所有数据    GET
27         queryset = BookInfo.objects.all()
28         serializer = BookInfoModelSerializer(queryset,many=True)
29         return Response(serializer.data)#返回数据
30 
31     def retrieve(self,request,pk=None):     #获取某一个      GET
32         queryset = BookInfo.objects.all()
33         user = get_object_or_404(queryset, pk=pk)
34         serializer = BookInfoModelSerializer(user)
35         return Response(serializer.data)#返回数据
36 
37 ##################################视图集 ModelViewSet##########################################
38 ##################################视图集  action ##########################################
39 
40 from rest_framework.viewsets import ModelViewSet
41 from rest_framework.decorators import action
42 
43 class BookModelViewSet(ModelViewSet):
44 
45     serializer_class = BookInfoModelSerializer
46     queryset = BookInfo.objects.all()
47 
48     """
49     单独给视图集添加方法(路由)
50 
51     1. 根据阅读量进行排序
52     2. 只修改某一本书籍的名字
53     """
54 
55     #根据阅读量进行排序
56     # methods=None,  设置 允许以什么请求访问该方法 默认是get
57     # detail=None
58     # 因为我们的Router是自动生成url的
59     # 如果detail 为True 表示 自动生成的url路由为: prefix/pk/函数名/
60     # 如果detail 为False 表示 自动生成的url路由为: prefix/函数名/
61     @action(methods=['GET'],detail=False)
62     def book_readcount(self,request):
63 
64         #1. 对数据进行排序
65         books = BookInfo.objects.all().order_by('readcount')
66         #2. 用序列化器将对象列表转换为字典列表
67         serialzier = self.get_serializer(books,many=True)
68         #3.返回
69         return Response(serialzier.data)#返回数据
70 
71     # detail为True表示单个实例,网址为这种形式:^prefix/{pk}/set_bookname/$
72     @action(methods=['post'], detail=True)
73     def set_bookname(self, request, pk=None):
74         book = self.get_object()
75         serializer = BookInfoModelSerializer(data=request.data)
76         if serializer.is_valid():
77             book.name = request.data['name']
78             book.save()
79             return Response({'message': '重置成功'})#返回数据
80         else:
81             return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)#返回数据
82 
83 
84 
85 from rest_framework.viewsets import ReadOnlyModelViewSet
86 class BookReadOnlyModelViewSet(ReadOnlyModelViewSet):
87     queryset = BookInfo.objects.all()
88     serializer_class = BookInfoModelSerializer
View Code
 1 from django.conf.urls import url
 2 from book import views
 3 
 4 from rest_framework.routers import DefaultRouter,SimpleRouter
 5 
 6 rounter = DefaultRouter()
 7 rounter.register(r'books',views.BookViewSet,base_name='')
 8 rounter.register(r'booksmodel',views.BookModelViewSet,base_name='')
 9 rounter.register(r'bookreadonlymodel',views.BookReadOnlyModelViewSet,base_name='')
10 
11 urlpatterns=[
12 
13 
14     # url(r'^books/$',views.BookViewSet.as_view({'get':'list'})),
15     # url(r'^books/(?P<pk>\d+)/$',views.BookViewSet.as_view({'get':'retrieve'})),
16 
17 ]
18 
19 urlpatterns += rounter.urls
20 app_name='book'
urls Code

 其他功能

1.认证Authentication

可以在配置文件中配置全局默认的认证方案

1 REST_FRAMEWORK = {
2     'DEFAULT_AUTHENTICATION_CLASSES': (
3         'rest_framework.authentication.BasicAuthentication',   # 基本认证
4         'rest_framework.authentication.SessionAuthentication',  # session认证
5     )
6 }
View Code

也可以在每个视图中通过设置authentication_classess属性来设置

 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #认证管理
 7 from rest_framework.authentication import SessionAuthentication
 8 
 9 
10 class BookModelViewSet(ModelViewSet):
11     """
12     图书管理视图
13     """
14     serializer_class = BookSerializer
15 
16     def get_queryset(self):
17         return BookInfo.objects.all()
18 
19     #认证管理
20     #认证管理一般和权限管理配合使用
21     # authentication_classes = [SessionAuthentication]
View Code

认证失败会有两种可能的返回值:

  • 401 Unauthorized 未认证
  • 403 Permission Denied 权限被禁止

2.权限Permissions

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

  • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
  • 在通过get_object()获取具体对象时,会进行对象访问权限的判断

使用

可以在配置文件中设置默认的权限管理类,如

1 REST_FRAMEWORK = {
2     'DEFAULT_PERMISSION_CLASSES': (
3         'rest_framework.permissions.IsAuthenticated',
4     )
5 }
View Code

如果未指明,则采用如下默认配置

1 'DEFAULT_PERMISSION_CLASSES': (
2    'rest_framework.permissions.AllowAny',
3 )
View Code

也可以在具体的视图中通过permission_classes属性来设置,如

 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #认证管理
 7 from rest_framework.authentication import SessionAuthentication
 8 #权限管理
 9 from rest_framework.permissions import IsAuthenticated,AllowAny,IsAdminUser
10 
11 
12 class BookModelViewSet(ModelViewSet):
13     """
14     图书管理视图
15     """
16     serializer_class = BookSerializer
17 
18     def get_queryset(self):
19         return BookInfo.objects.all()
20 
21     #认证管理
22     #认证管理一般和权限管理配合使用
23     # authentication_classes = [SessionAuthentication] #权限管理
24     # 通过python manager createsuperuser 就可以创建一个管理员账号,登录之后就可以访问
25     # permission_classes = [IsAuthenticated]
View Code

提供的权限

  • AllowAny 允许所有用户
  • IsAuthenticated 仅通过认证的用户
  • IsAdminUser 仅管理员用户
  • IsAuthenticatedOrReadOnly 认证的用户可以完全操作,否则只能get读取

举例

1 from rest_framework.authentication import SessionAuthentication
2 from rest_framework.permissions import IsAuthenticated
3 from rest_framework.generics import RetrieveAPIView
4 
5 class BookDetailView(RetrieveAPIView):
6     queryset = BookInfo.objects.all()
7     serializer_class = BookInfoSerializer
8     authentication_classes = [SessionAuthentication]
9     permission_classes = [IsAuthenticated]
View Code

自定义权限

如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部

  • has_permission(self, request, view)

    是否可以访问视图, view表示当前视图对象

  • has_object_permission(self, request, view, obj)

    是否可以访问数据对象, view表示当前视图, obj为数据对象

  • class MyPermission(BasePermission):
        def has_object_permission(self, request, view, obj):
            """控制对obj对象的访问权限,此案例决绝所有对对象的访问"""
            return False
    
    class BookInfoViewSet(ModelViewSet):
        queryset = BookInfo.objects.all()
        serializer_class = BookInfoSerializer
        permission_classes = [IsAuthenticated, MyPermission]

     

3.限流Throttling

微博限流文档

可以对接口访问的频次进行限制,以减轻服务器压力。

使用

可以在配置文件中,使用DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES进行全局配置,

 1 REST_FRAMEWORK = {
 2     'DEFAULT_THROTTLE_CLASSES': (
 3         'rest_framework.throttling.AnonRateThrottle',
 4         'rest_framework.throttling.UserRateThrottle'
 5     ),
 6     'DEFAULT_THROTTLE_RATES': {
 7         'anon': '100/day',
 8         'user': '1000/day'
 9     }
10 }
11 #DEFAULT_THROTTLE_RATES可以使用second,minute,hour或day来指明周期。
View Code

也可以在具体视图中通过throttle_classess属性来配置,如

1 from rest_framework.throttling import UserRateThrottle
2 from rest_framework.views import APIView
3 
4 class ExampleView(APIView):
5     throttle_classes = (UserRateThrottle,)
6     ...
View Code

可选限流类

1) AnonRateThrottle限制所有匿名未认证用户,使用IP区分用户。

使用DEFAULT_THROTTLE_RATES['anon']来设置频次

2)UserRateThrottle限制认证用户,使用User id 来区分。

使用DEFAULT_THROTTLE_RATES['user']来这是频次

3)ScopedRateThrottle限制用户对于每个视图的访问频次,使用ip或user id。

例如:

 1 class ContactListView(APIView):
 2     throttle_scope = 'contacts'
 3     ...
 4 
 5 class ContactDetailView(APIView):
 6     throttle_scope = 'contacts'
 7     ...
 8 
 9 class UploadView(APIView):
10     throttle_scope = 'uploads'
11     ...
12 REST_FRAMEWORK = {
13     'DEFAULT_THROTTLE_CLASSES': (
14         'rest_framework.throttling.ScopedRateThrottle',
15     ),
16     'DEFAULT_THROTTLE_RATES': {
17         'contacts': '1000/day',
18         'uploads': '20/day'
19     }
20 }
View Code

实例

 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #认证管理
 7 from rest_framework.authentication import SessionAuthentication
 8 #权限管理
 9 from rest_framework.permissions import IsAuthenticated,AllowAny,IsAdminUser
10 #限流
11 from rest_framework.throttling import UserRateThrottle,AnonRateThrottle,ScopedRateThrottle
12 
13 class BookModelViewSet(ModelViewSet):
14     """
15     图书管理视图
16     """
17     serializer_class = BookSerializer
18 
19     def get_queryset(self):
20         return BookInfo.objects.all()
21 
22     #认证管理
23     #认证管理一般和权限管理配合使用
24     # authentication_classes = [SessionAuthentication]
25     #权限管理
26     # 通过python manager createsuperuser 就可以创建一个管理员账号,登录之后就可以访问
27     # permission_classes = [IsAuthenticated]
28     #限流
29     throttle_classes = [AnonRateThrottle]
View Code

4.过滤Filtering

文档

对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

pip install django-filter
安装应用:
INSTALLED_APPS = [
    ...
    'django_filters',
    ...
]

在配置文件中增加过滤后端的设置:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
在视图中添加filter_fields属性,指定可以过滤的字段
 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 class BookModelViewSet(ModelViewSet):
 7     """
 8     图书管理视图
 9     """
10     serializer_class = BookSerializer
11 
12     def get_queryset(self):
13         return BookInfo.objects.all()
14 
15     #过滤
16     filter_fields = ['id','name','pub_date']
17 
18 # 127.0.0.1:8000/books/?name=西游记
View Code

5.排序OrderingFilter

文档

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

使用方法:

在类视图中设置filter_backends,使用rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

示例:

 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #排序
 7 from rest_framework.filters import OrderingFilter
 8 
 9 
10 class BookModelViewSet(ModelViewSet):
11     """
12     图书管理视图
13     """
14     serializer_class = BookSerializer
15 
16     def get_queryset(self):
17         return BookInfo.objects.all()
18 
19     #排序
20     filter_backends = [OrderingFilter]
21     ordering_fields = ['id','readcount','commentcount']
22 
23     # 127.0.0.1:8000/books/?ordering=-readcount
View Code

6.分页Pagination

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

1 REST_FRAMEWORK = {
2     'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
3     'PAGE_SIZE': 100  # 每页数目
4 }
View Code

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过pagination_clas属性来指明。

1 class LargeResultsSetPagination(PageNumberPagination):
2     page_size = 1000
3     page_size_query_param = 'page_size'
4     max_page_size = 10000
5 class BookDetailView(RetrieveAPIView):
6     queryset = BookInfo.objects.all()
7     serializer_class = BookInfoSerializer
8     pagination_class = LargeResultsSetPagination
View Code

可选分页器

1)PageNumberPagination

前端访问网址形式:

GET  http://api.example.org/books/?page=4

可以在子类中定义的属性:

  • page_size 每页数目
  • page_query_param 前端发送的页数关键字名,默认为"page"
  • page_size_query_param 前端发送的每页数目关键字名,默认为None
  • max_page_size 前端最多能设置的每页数量
 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #分页
 7 from rest_framework.pagination import PageNumberPagination
 8 class StandartPageNumberPagination(PageNumberPagination):
 9     page_size = 2                   #默认每页返回的条数
10     max_page_size = 50              #每页返回的最大条数
11     page_size_query_param = 'ps'    #url中设置 page_size的键,默认为page_size
12     page_query_param = 'p'          #url中设置 page的键,默认为page
13 
14 class BookModelViewSet(ModelViewSet):
15     """
16     图书管理视图
17     """
18     serializer_class = BookSerializer
19 
20     def get_queryset(self):
21 
22         return BookInfo.objects.all()
23     #分页
24     pagination_class = StandartPageNumberPagination
25 
26     #http://127.0.0.1:8000/books/?p=1&ps=4
View Code

2)LimitOffsetPagination

前端访问网址形式:

GET http://api.example.org/books/?limit=100&offset=400

可以在子类中定义的属性:

  • default_limit 默认限制,默认值与PAGE_SIZE设置一致
  • limit_query_param limit参数名,默认'limit'
  • offset_query_param offset参数名,默认'offset'
  • max_limit 最大limit限制,默认None
 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 #分页
 7 from rest_framework.pagination import LimitOffsetPagination
 8 
 9 
10 class BookModelViewSet(ModelViewSet):
11     """
12     图书管理视图
13     """
14     serializer_class = BookSerializer
15 
16     def get_queryset(self):
17 
18         return BookInfo.objects.all()
19 
20     pagination_class = LimitOffsetPagination
21     # http://127.0.0.1:8000/books/?limit=2&offset=4
View Code

7.异常处理 Exceptions

文档

REST framework提供了异常处理,我们可以自定义异常处理函数。例如处理关于数据库的异常

 1 from rest_framework.views import exception_handler
 2 from rest_framework import status
 3 from django.db import DatabaseError
 4 from rest_framework.response import Response
 5 
 6 def custom_exception_handler(exc, context):
 7     #exc 当前异常的对象
 8     #context 哪个地方出的问题
 9 
10     #先调用REST framework默认的异常处理方法获得标准错误响应对象
11     response = exception_handler (exc, context)
12     #在此处补充自定义的异常处理
13     if response is None:
14         view = context['view']
15         if isinstance(exc, DatabaseError):
16             print('[%s]: %s' % (view, exc))
17             response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)
18 
19     return response
View Code

在配置文件中声明自定义的异常处理

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'book.exceptions.custom_exception_handler'
}

如果未声明,会采用默认的方式,如下

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}

手动触发异常

 1 from rest_framework.viewsets import ModelViewSet
 2 from .serializers import BookSerializer
 3 from .models import BookInfo
 4 # Create your views here.
 5 
 6 
 7 
 8 class BookModelViewSet(ModelViewSet):
 9     """
10     图书管理视图
11     """
12     serializer_class = BookSerializer
13 
14     def get_queryset(self):
15 
16         from django.db import DatabaseError
17         raise DatabaseError('error')
18 
19         return BookInfo.objects.all()
View Code

REST framework定义的异常

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限决绝
  • NotFound 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败

8.自动生成接口文档

REST framework可以自动帮助我们生成接口文档。

接口文档以网页的方式呈现。

自动接口文档能生成的是继承自APIView及其子类的视图。

1. 安装依赖

REST framewrok生成接口文档需要coreapi库的支持。

pip install coreapi

2. 设置接口文档访问路径

在总路由中添加接口文档路径。

文档路由对应的视图配置为rest_framework.documentation.include_docs_urls

参数title为接口文档网站的标题。

from rest_framework.documentation import include_docs_urls

urlpatterns = [
    ...
    url(r'^docs/', include_docs_urls(title='API接口文档'))
]

3. 文档描述说明的定义位置

1) 单一方法的视图,可直接使用类视图的文档字符串,如

class BookListView(generics.ListAPIView):
    """
    返回所有图书信息.
    """

2)包含多个方法的视图,在类视图的文档字符串中,分开方法定义,如

class BookListCreateView(generics.ListCreateAPIView):
    """
    get:
    返回所有图书信息.

    post:
    新建图书.
    """

 

3)对于视图集ViewSet,仍在类视图的文档字符串中封开定义,但是应使用action名称区分,如

class BookInfoViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    """
    list:
    返回图书列表数据

    retrieve:
    返回图书详情数据

    latest:
    返回最新的图书数据

    read:
    修改图书的阅读量
    """

 

4. 访问接口文档网页

浏览器访问 127.0.0.1:8000/docs/,即可看到自动生成的接口文档。

两点说明:

1) 视图集ViewSet中的retrieve名称,在接口文档网站中叫做read

2)参数的Description需要在模型类或序列化器类的字段中以help_text选项定义,如:

 1 class BookInfo(models.Model):
 2     ...
 3     readcount= models.IntegerField(default=0, verbose_name='阅读量', help_text='阅读量')
 4     ...
 5  6 
 7 class BookSerializer(serializers.ModelSerializer):
 8 
 9     class Meta:
10         model = BookInfo
11         fields = '__all__'
12         extra_kwargs = {
13             'readcount':{
14                 'help_text':'阅读量'
15             }
16         }
View Code

 

转载于:https://www.cnblogs.com/returnes/p/10203329.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值