Django中views笔记

时间:2023-03-09 18:46:06
Django中views笔记

reverse反解析

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

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对象。

 # /get/?a=1&b=2&a=3

 def get(request):
a = request.GET.get('a')
b = request.GET.get('b')
alist = request.GET.getlist('a')
print(a) #
print(b) #
print(alist) # ['1', '3']
return HttpResponse('OK')

3.表单类型 Form Data

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

 def post(request):
a = request.POST.get('a')
b = request.POST.get('b')
alist = request.POST.getlist('a')
print(a)
print(b)
print(alist)
return HttpResponse('OK')

4.非表单类型 Non-Form Data

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

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

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

可以进行如下方法操作:

 import json

 def post_json(request):
json_str = request.body
json_str = json_str.decode() # python3.6 无需执行此步
req_data = json.loads(json_str)
print(req_data['a'])
print(req_data['b'])
return HttpResponse('OK')

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=状态码)
 from django.http import HttpResponse

 def response(request):
return HttpResponse('itcast python', status=400)
或者
response = HttpResponse('itcast python')
response.status_code = 400
response['itcast'] = 'Python'
return response

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
 from django.http import JsonResponse

 def response(request):
return JsonResponse({'city': 'beijing', 'subject': 'python'})

4 redirect重定向

 from django.shortcuts import redirect

 def response(request):
return redirect('/get_header')

cookie和session

示例代码:

 def set_cookie(request):
'''设置cookie'''
name=request.GET.get('name')
pwd=request.GET.get('pwd')
response=HttpResponse('set cookie')
response.set_cookie('name',name)
response.set_cookie('pwd',pwd,max_age=60)
return response def get_cookie(request):
'''获取cookie'''
name=request.COOKIES.get('name')
pwd=request.COOKIES.get('pwd')
return HttpResponse("name:%s,pwd:%s"%(name,pwd)) def del_cookie(request):
'''删除cookie'''
response=HttpResponse('del cookie')
response.delete_cookie('name')
return response def to_session(request):
'''session操作'''
name=request.COOKIES.get('name')
# 1) 以键值对的格式写session。
request.session['name']=name
# 2)根据键读取值。
session_name=request.session.get('name')
return HttpResponse('%s'%session_name)
# 3)清除所有session,在存储中删除值部分。
request.session.clear()
# 4)清除session数据,在存储中删除session的整条数据。
request.session.flush()
# 5)删除session中的指定键及值,在存储中只删除某个键及对应的值。
del request.session['name']
# 6)设置session的有效期单位秒
request.session.set_expiry(60)

中间件

1 .中间件的定义方法

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

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

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

 def simple_middleware(get_response):
# 此处编写的代码仅在Django第一次配置和初始化的时候执行一次。 def middleware(request):
# 此处编写的代码会在每个请求处理视图前被调用。 response = get_response(request) # 此处编写的代码会在每个请求处理视图之后被调用。 return response return middleware

示例代码

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

 def my_middleware(get_response):
print('init 被调用')
def middleware(request):
print('before request 被调用')
response = get_response(request)
print('after response 被调用')
return response
return middleware

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

 MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'book.middleware.my_middleware', # 添加中间件
]

rest_framework实现序列化器

1.配置文件setting

INSTALLED_APPS = [
'rest_framework'
]

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

  方式一继承Serializer

 from rest_framework import serializers

 from book.models import BookInfo

 class BookInfoSerializer(serializers.Serializer):
'''书籍数据序列化''' def custom_validate(value):
if value == 'hehe':
raise serializers.ValidationError('书名不能为hehe') id = serializers.IntegerField(label='id', read_only=True)
name = serializers.CharField(label='书名', max_length=20, validators=[custom_validate]) # validators为自定义限定函数集
click_count = serializers.IntegerField(label='点击量', required=False)
scan_count = serializers.IntegerField(label='浏览量', required=False)
image = serializers.ImageField(label='封面', required=False)
create_time = serializers.DateTimeField(label='创建时间', required=False)
peopleinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) def validate_click_count(self, value): # 指定字段限定条件,命名方式为validate_字段名,接收字段值value
if value < 0:
raise serializers.ValidationError('点击量不能小于0')
return value def validate_scan_count(self, value):
if value < 0:
raise serializers.ValidationError('浏览量不能小于0')
return value def validate(self, attrs): # 多个字段限定条件,固定函数名validate,传入字典字段值attrs
click_count = attrs.get('click_count')
scan_count = attrs.get('scan_count')
if click_count > scan_count:
raise serializers.ValidationError('浏览量不能小于点击量')
return attrs def create(self, validated_data):
'''新增数据'''
return BookInfo.objects.create(**validated_data) def update(self, instance, validated_data):
'''更新数据'''
instance.name = validated_data.get('name', instance.name)
instance.click_count = validated_data.get('click_count', instance.click_count)
instance.scan_count = validated_data.get('scan_count', instance.scan_count)
instance.create_time = validated_data.get('create_time', instance.create_time)
instance.save()
return instance

  方式二继承ModelSerializer

 from rest_framework import serializers

 from book.models import BookInfo

 class BookInfoSerializers(serializers.ModelSerializer):
class Meta:
model = BookInfo
# fields='__all__' #取所有字段
# fields=['id','name','click_count'] # 取该字典中的字段
exclude = ['image'] # 取除了该字段的其他字段
read_only_fields = ['id', 'click_count', 'scan_count'] # 只读字段
# 字段限定条件
extra_kwargs = {
'click_count': {'min_value': 0, 'required': True},
'scan_count': {'min_value': 0, 'required': True}
}

rest_framework实现三个级别view

1.setting中增加如下:

 REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器
)
}

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

 # 一级视图 继承类 from rest_framework.views import APIView
from django.shortcuts import render
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer class BookListView(APIView):
def get(self, request):
books = BookInfo.objects.all() #获取BookInfo模型所有数据
serializer = BookInfoModelSerializer(books, many=True) #初始化BookInfoModelSerializer序列化器
return Response(serializer.data) #返回数据 def post(self, request):
data = request.data #获取请求数据
serializer = BookInfoModelSerializer(data=data) #初始化BookInfoModelSerializer序列化器
serializer.is_valid(raise_exception=True)#校验请求的数据,如果有异常抛出异常
serializer.save()# 保存操作
return Response(serializer.data)#返回数据 class BookDetailView(APIView):
def get(self, request, id):
book = BookInfo.objects.get(id=id) #查询模型BookInfo中指定数据
serializer = BookInfoModelSerializer(book) #初始化BookInfoModelSerializer序列化器
return Response(serializer.data) #返回数据 def put(self, request, id):
book = BookInfo.objects.get(id=id)#查询模型BookInfo中指定数据
data = request.data# 获取请求数据
serializer = BookInfoModelSerializer(book, data=data)#初始化BookInfoModelSerializer序列化器
serializer.is_valid(raise_exception=True) #校验数据,如异常抛出
serializer.save() #保存数据
return Response(serializer.data)#返回数据 def delete(self, request, id):
book = BookInfo.objects.get(id=id)# 查询模型BookInfo中指定数据
book.delete()# 删除数据
return Response(status=status.HTTP_204_NO_CONTENT)#返回状态
 urlpatterns=[
# 一级视图 继承类 from rest_framework.views import APIView
url(r'^booklist/$',views.BookListView.as_view(),name='booklist'),
url(r'^bookdetail/(?P<id>\d+)$',views.BookDetailView.as_view(),name='bookdetail'),
]

urls Code

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

 # 二级视图 继承类 from rest_framework.generics import GenericAPIView
from rest_framework.generics import GenericAPIView
from book.models import BookInfo
from book.serializers import BookInfoModelSerializer
from rest_framework.response import Response class BookListGenericAPIView(GenericAPIView):
queryset = BookInfo.objects.all()# 获取所有数据赋值给queryset
serializer_class = BookInfoModelSerializer #初始化序列化器属性 def get(self, request):
books = self.get_queryset() # 通过父类方法获取queryset
serializer = self.get_serializer(books, many=True) # 通过父类方法获取serializer_class
return Response(serializer.data) #返回数据 def post(self, request):
data = request.data #获取请求数据
serializer = self.get_serializer(data=data)
serializer.is_valid(raise_exception=True)#校验数据,如异常抛出
serializer.save()#保存数据
return Response(serializer.data)#返回数据 class BookDetailGenericAPIView(GenericAPIView):
queryset = BookInfo.objects.all()# 获取所有数据赋值给queryset
serializer_class = BookInfoModelSerializer#初始化序列化器属性
# lookup_field = 'pk' #默认参数为pk
lookup_field = 'id' # 可重写父类属性 def get(self, request, id):
book = self.get_object()#通过父类方法获取模型中指定数据
serializer = self.get_serializer(book)# 通过父类方法获取序列化器
return Response(serializer.data)#返回数据 def put(self, request, id):
book = self.get_object()
serializer = self.get_serializer(instance=book, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)#返回数据 def delete(self, request, id):
book = self.get_object()
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)#返回状态
 urlpatterns=[
# 二级视图 继承类 from rest_framework.generics import GenericAPIView
url(r'^booklistgeneric/$', views.BookListGenericAPIView.as_view(), name='booklistgeneric'),
url(r'^bookdetailgeneric/(?P<id>\d+)$', views.BookDetailGenericAPIView.as_view(), name='bookdetailgeneric'),
]

urls Code

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

 # 二级视图和Mixin配合使用,Mixin中已经封装了get、post、get、put、delete相应功能,对应方法list、create、retrieve、update、destroy
from rest_framework.mixins import ListModelMixin, CreateModelMixin
from rest_framework.mixins import RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
from rest_framework.generics import GenericAPIView class BookListMixinGenericAPIView(ListModelMixin, CreateModelMixin, GenericAPIView):
# queryset = BookInfo.objects.all()
# serializer_class = BookInfoModelSerializer
# 重写父类方法,获取数据
def get_queryset(self):
return BookInfo.objects.all() # 重写父类方法,设置序列化器
def get_serializer_class(self):
return BookInfoModelSerializer def get(self, request):
return self.list(request) def post(self, request):
return self.create(request) class BookDetailMixinGenericAPIView(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, GenericAPIView):
# 获取所有数据赋值给queryset
queryset = BookInfo.objects.all()
# 设置序列化器属性
serializer_class = BookInfoModelSerializer def get(self, request, pk):
return self.retrieve(request) def put(self, request, pk):
return self.update(request) def delete(self, request, pk):
return self.destroy(request)
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.三级视图,高度封装

 # 三级视图,高度封装
from rest_framework.generics import CreateAPIView,ListAPIView
class BookListAPIView(ListAPIView,CreateAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView
class DetailAPIView(RetrieveAPIView, UpdateAPIView, DestroyAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer from rest_framework.generics import RetrieveDestroyAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView
 urlpatterns=[
# 三级视图
url(r'^booklistapiview/$', views.BookListAPIView.as_view(), name='booklistapiview'),
url(r'^detailapiview/(?P<pk>\d+)$', views.DetailAPIView.as_view(), name='detailapiview'), ]

urls Code

5.视图集ViewSet、ModelViewSet、ReadOnlyModelViewSet

 ##################################视图集 ##########################################

 """
1. 有相同的相关业务逻辑 (对一个模型的 增删改查的操作)
2. 列表试图和详情视图中 有重复的属性 我们想到把 增删改查 放到一个视图中
class Index(View): def list() get
pass def retrieve() get
pass """
from rest_framework.viewsets import ViewSet from rest_framework.viewsets import ViewSet
from django.shortcuts import get_object_or_404
from rest_framework.response import Response class BookViewSet(ViewSet): def list(self,request): # 获取所有数据 GET
queryset = BookInfo.objects.all()
serializer = BookInfoModelSerializer(queryset,many=True)
return Response(serializer.data)#返回数据 def retrieve(self,request,pk=None): #获取某一个 GET
queryset = BookInfo.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = BookInfoModelSerializer(user)
return Response(serializer.data)#返回数据 ##################################视图集 ModelViewSet##########################################
##################################视图集 action ########################################## from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action class BookModelViewSet(ModelViewSet): serializer_class = BookInfoModelSerializer
queryset = BookInfo.objects.all() """
单独给视图集添加方法(路由) 1. 根据阅读量进行排序
2. 只修改某一本书籍的名字
""" #根据阅读量进行排序
# methods=None, 设置 允许以什么请求访问该方法 默认是get
# detail=None
# 因为我们的Router是自动生成url的
# 如果detail 为True 表示 自动生成的url路由为: prefix/pk/函数名/
# 如果detail 为False 表示 自动生成的url路由为: prefix/函数名/
@action(methods=['GET'],detail=False)
def book_readcount(self,request): #1. 对数据进行排序
books = BookInfo.objects.all().order_by('readcount')
#2. 用序列化器将对象列表转换为字典列表
serialzier = self.get_serializer(books,many=True)
#3.返回
return Response(serialzier.data)#返回数据 # detail为True表示单个实例,网址为这种形式:^prefix/{pk}/set_bookname/$
@action(methods=['post'], detail=True)
def set_bookname(self, request, pk=None):
book = self.get_object()
serializer = BookInfoModelSerializer(data=request.data)
if serializer.is_valid():
book.name = request.data['name']
book.save()
return Response({'message': '重置成功'})#返回数据
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)#返回数据 from rest_framework.viewsets import ReadOnlyModelViewSet
class BookReadOnlyModelViewSet(ReadOnlyModelViewSet):
queryset = BookInfo.objects.all()
serializer_class = BookInfoModelSerializer
 from django.conf.urls import url
from book import views from rest_framework.routers import DefaultRouter,SimpleRouter rounter = DefaultRouter()
rounter.register(r'books',views.BookViewSet,base_name='')
rounter.register(r'booksmodel',views.BookModelViewSet,base_name='')
rounter.register(r'bookreadonlymodel',views.BookReadOnlyModelViewSet,base_name='') urlpatterns=[ # url(r'^books/$',views.BookViewSet.as_view({'get':'list'})),
# url(r'^books/(?P<pk>\d+)/$',views.BookViewSet.as_view({'get':'retrieve'})), ] urlpatterns += rounter.urls
app_name='book'

urls Code

 其他功能

1.认证Authentication

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

 REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication', # 基本认证
'rest_framework.authentication.SessionAuthentication', # session认证
)
}

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

 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #认证管理
from rest_framework.authentication import SessionAuthentication class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self):
return BookInfo.objects.all() #认证管理
#认证管理一般和权限管理配合使用
# authentication_classes = [SessionAuthentication]

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

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

2.权限Permissions

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

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

使用

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

 REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}

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

 'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)

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

 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #认证管理
from rest_framework.authentication import SessionAuthentication
#权限管理
from rest_framework.permissions import IsAuthenticated,AllowAny,IsAdminUser class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self):
return BookInfo.objects.all() #认证管理
#认证管理一般和权限管理配合使用
# authentication_classes = [SessionAuthentication] #权限管理
# 通过python manager createsuperuser 就可以创建一个管理员账号,登录之后就可以访问
# permission_classes = [IsAuthenticated]

提供的权限

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

举例

 from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import RetrieveAPIView class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]

自定义权限

如需自定义权限,需继承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进行全局配置,

 REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
),
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day',
'user': '1000/day'
}
}
#DEFAULT_THROTTLE_RATES可以使用second,minute,hour或day来指明周期。

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

 from rest_framework.throttling import UserRateThrottle
from rest_framework.views import APIView class ExampleView(APIView):
throttle_classes = (UserRateThrottle,)
...

可选限流类

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

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

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

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

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

例如:

 class ContactListView(APIView):
throttle_scope = 'contacts'
... class ContactDetailView(APIView):
throttle_scope = 'contacts'
... class UploadView(APIView):
throttle_scope = 'uploads'
...
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.ScopedRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'contacts': '1000/day',
'uploads': '20/day'
}
}

实例

 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #认证管理
from rest_framework.authentication import SessionAuthentication
#权限管理
from rest_framework.permissions import IsAuthenticated,AllowAny,IsAdminUser
#限流
from rest_framework.throttling import UserRateThrottle,AnonRateThrottle,ScopedRateThrottle class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self):
return BookInfo.objects.all() #认证管理
#认证管理一般和权限管理配合使用
# authentication_classes = [SessionAuthentication]
#权限管理
# 通过python manager createsuperuser 就可以创建一个管理员账号,登录之后就可以访问
# permission_classes = [IsAuthenticated]
#限流
throttle_classes = [AnonRateThrottle]

4.过滤Filtering

文档

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

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

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

REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}
在视图中添加filter_fields属性,指定可以过滤的字段
 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self):
return BookInfo.objects.all() #过滤
filter_fields = ['id','name','pub_date'] # 127.0.0.1:8000/books/?name=西游记

5.排序OrderingFilter

文档

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

使用方法:

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

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

示例:

 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #排序
from rest_framework.filters import OrderingFilter class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self):
return BookInfo.objects.all() #排序
filter_backends = [OrderingFilter]
ordering_fields = ['id','readcount','commentcount'] # 127.0.0.1:8000/books/?ordering=-readcount

6.分页Pagination

REST framework提供了分页的支持。

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

 REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100 # 每页数目
}

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

 class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class BookDetailView(RetrieveAPIView):
queryset = BookInfo.objects.all()
serializer_class = BookInfoSerializer
pagination_class = LargeResultsSetPagination

可选分页器

1)PageNumberPagination

前端访问网址形式:

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

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

  • page_size 每页数目
  • page_query_param 前端发送的页数关键字名,默认为"page"
  • page_size_query_param 前端发送的每页数目关键字名,默认为None
  • max_page_size 前端最多能设置的每页数量
 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #分页
from rest_framework.pagination import PageNumberPagination
class StandartPageNumberPagination(PageNumberPagination):
page_size = 2 #默认每页返回的条数
max_page_size = 50 #每页返回的最大条数
page_size_query_param = 'ps' #url中设置 page_size的键,默认为page_size
page_query_param = 'p' #url中设置 page的键,默认为page class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self): return BookInfo.objects.all()
#分页
pagination_class = StandartPageNumberPagination #http://127.0.0.1:8000/books/?p=1&ps=4

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
 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. #分页
from rest_framework.pagination import LimitOffsetPagination class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self): return BookInfo.objects.all() pagination_class = LimitOffsetPagination
# http://127.0.0.1:8000/books/?limit=2&offset=4

7.异常处理 Exceptions

文档

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

 from rest_framework.views import exception_handler
from rest_framework import status
from django.db import DatabaseError
from rest_framework.response import Response def custom_exception_handler(exc, context):
#exc 当前异常的对象
#context 哪个地方出的问题 #先调用REST framework默认的异常处理方法获得标准错误响应对象
response = exception_handler (exc, context)
#在此处补充自定义的异常处理
if response is None:
view = context['view']
if isinstance(exc, DatabaseError):
print('[%s]: %s' % (view, exc))
response = Response({'detail': '服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) return response

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

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

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

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

手动触发异常

 from rest_framework.viewsets import ModelViewSet
from .serializers import BookSerializer
from .models import BookInfo
# Create your views here. class BookModelViewSet(ModelViewSet):
"""
图书管理视图
"""
serializer_class = BookSerializer def get_queryset(self): from django.db import DatabaseError
raise DatabaseError('error') return BookInfo.objects.all()

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/,即可看到自动生成的接口文档。

Django中views笔记

两点说明:

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

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

 class BookInfo(models.Model):
...
readcount= models.IntegerField(default=0, verbose_name='阅读量', help_text='阅读量')
...
或 class BookSerializer(serializers.ModelSerializer): class Meta:
model = BookInfo
fields = '__all__'
extra_kwargs = {
'readcount':{
'help_text':'阅读量'
}
}