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_CLASSES
和DEFAULT_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/,即可看到自动生成的接口文档。
两点说明:
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':'阅读量'
}
}
Django中views笔记的更多相关文章
- django中views中方法的request参数
知其然亦要知其所以然 views每个方法的参数都是request,那么问题来了,request为何物? 首先,几乎每个方法都是取数据(无论是从数据库,还是从第三方接口),然后进行一定的处理,之后传给前 ...
- Django中views数据查询使用locals()函数进行优化
优化场景 利用视图函数(views)查询数据之后可以通过上下文context.字典.列表等方式将数据传递给HTML模板,由template引擎接收数据并完成解析.但是通过context传递数据可能就存 ...
- django 中的视图(Views)
Views Django中views里面的代码就是一个一个函数逻辑, 处理客户端(浏览器)发送的HTTPRequest, 然后返回HTTPResponse, http请求中产生两个核心对象: http ...
- Redis缓存在django中的配置
django settings中的配置 # 缓存 CACHES = { "default": { "BACKEND": "django_redis. ...
- PyCharm中Django项目主urls导入应用中views的红线问题
PyCharm中Django项目主urls导入应用中views的红线问题 使用PyCharm学习Django框架,从项目的主urls中导入app中的views的时候,导入的包中下面有红线报错,但是却能 ...
- 测试开发之Django——No3.Django中的试图(views)
说到views,我们先来说django中执行的一个顺序. 我们打开一个django中配置的页面,之后的执行是有这么几个步骤: 1.系统配置的urls中寻找是否配置了这个地址: 2.如果已经配置了这个地 ...
- Python之Django之views中视图代码重复查询的优化
Django框架中views视图中如果多个函数都有同样的查询语句,例如: allcategory = Category.objects.all() remen = Article.objects.fi ...
- django中models阅读笔记
一.使用数据库需要设置settings.py文件. DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', # Add 'postgre ...
- Django初识 学习笔记一
Django初识 学习笔记一 mvcviewsmodelstemplate. 一 MVC框架 MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(c ...
随机推荐
- Cordova开箱注意事项
在进行cd 目录切换的时候 一定要 注意大小写 不然 node_modules 下的依赖包 会报错 区分大小写 Cordova 在打包的时候报错 一般是版本或sdk问题 cordova 的版本要和co ...
- postgresql之json操作
--string 转 json select '{"Items":[{"Id":1,"InitStartDate":"2018-0 ...
- 解决 Cannot get IBus daemon address 问题
参考: Cannot get IBus daemon address 解决 Cannot get IBus daemon address 问题 在 Ubuntu 14.04 系统下使用 TexMake ...
- Date日期类型的绑定
自定义类型的绑定 springmvc没有提供默认的对日期类型的绑定,需要自定义日期类型的绑定 第一张图是po类中日期属性,第二张图是页面中日期属性的内容,第三张图片是访问出现400错误 因为日期的格式 ...
- TF-IDF 提取关键词
<?php class Document { protected $words; protected $tf_matrix; protected $tfidf_matrix; public fu ...
- VS code 推荐插件
vs code 中eslint语法检测,保存即可格式化 具体查看:(https://www.jianshu.com/p/23a5d6194a4b) { // vscode默认启用了根据文件类型自动设置 ...
- tomcat: 类加载器
一.tomcat是个web容器,要解决以下问题 1. 一个web容器可能要部署两个或者多个应用程序,不同的应用程序,可能会依赖同一个第三方类库的不同版本,因此要保证每一个应用程序的类库都是独立.相互隔 ...
- java网络编程小白教程
1 网络编程 1.1 网络 把多台终端(计算机)通过物理线路连接起来,形成网络.便于交换数据.共享信息.组成更强大的逻辑体. 1.1.1 网络通信三要素 [1]IP地址:唯一标识网络上的每一台计算机 ...
- python 【pandas】账号、银行卡号、身份证号导出文件后以科学计数法显示问题解决
问题描述:excel表中的一些数据会以文本格式格式保存,例如一些较长的编号.银行账号.身份证号等,再python中导出文件后,会发现数据以科学计数法显示,影响后续使用. data2_3.to_exce ...
- 搭建Python自动化测试环境+元素定位
https://blog.csdn.net/GitChat/article/details/79081187