您好,登錄后才能下訂單哦!
?
目錄
django rest ?framework. 1
serializers.Serializer. 1
serializers.ModelSerializer:... 3
api FBV:... 4
rest_framework.request.Request和rest_framework.response.Response:... 5
rest_framework.decorators.api_view和rest_framework.views.APIView:... 5
api CBV,rest_framework.views.APIView:... 6
api CBV,使用rest_framework.mixins:... 7
api CBV,使用generics.ListCreateAPIView和generics.RetrieveUpdateDestroyAPIView:... 8
分頁:... 9
認證:... 9
授權:... 10
?
?
?
?
是django用來restful api的框架,風格完全和django一樣,使用起來像是django本身提供的;
?
https://www.django-rest-framework.org/
?
(webproject) C:\webproject\mysite>pip install djangorestframework
?
INSTALLED_APPS = [
??? 'rest_framework',
?
?
rest_framework.serializers.Serializer和django.forms.Form:
功能一樣,都是將用戶提交的數據轉為py數據結構,可用此來完成校驗;
?
Form用在post提交中的form表單;
Serializer用在用戶提交的json;
?
?
from rest_framework import serializers
from .models import Author
?
class AuthorSerializer(serializers.Serializer):
??? id = serializers.IntegerField(read_only=True)
??? first_name = serializers.CharField(max_length=100)
??? last_name = serializers.CharField(required=False, allow_blank=True, max_length=100)
??? email = serializers.EmailField(required=False, allow_blank=True, max_length=100)
?
??? def create(self, validated_data):
??????? return Author.objects.create(**validated_data)
?
??? def update(self, instance, validated_data):
??????? instance.first_name = validated_data.get('first_name', instance.first_name)
??????? instance.last_name = validated_data.get('last_name', instance.last_name)
??????? instance.email = validated_data.get('email', instance.email)
??????? instance.save()
??????? return instance
?
?
底層實現:
>>> from books.serializer import AuthorSerializer
>>> from rest_framework.renderers import JSONRenderer?? #py結構-->json
>>> from rest_framework.parsers import JSONParser?? #json-->py結構
>>> from books.models import Author
>>> Author.objects.all()
<QuerySet [<Author: chai jowin>, <Author: dsfdfd sfdsfdsf>]>
>>> a = Author.objects.get(id=1)
>>> s = AuthorSerializer(a)
>>> s.data?? #dict
{'last_name': 'jowin', 'email': 'jowin@chai.com', 'id': 1, 'first_name': 'chai'}
>>> content = JSONRenderer().render(s.data)
>>> content
b'{"id":1,"first_name":"chai","last_name":"jowin","email":"jowin@chai.com"}'
?
>>> from django.utils.six import BytesIO
>>> stream = BytesIO(content)
>>> stream
<_io.BytesIO object at 0x00000000046389E8>
>>> data = JSONParser().parse(stream)
>>> data
{'last_name': 'jowin', 'email': 'jowin@chai.com', 'id': 1, 'first_name': 'chai'}
>>> s = AuthorSerializer(data=data)
>>> s
AuthorSerializer(data={'last_name': 'jowin', 'email': 'jowin@chai.com', 'id': 1, 'first_name': 'chai'}):
??? id = IntegerField(read_only=True)
??? first_name = CharField(max_length=100)
??? last_name = CharField(allow_blank=True, max_length=100, required=False)
??? email = EmailField(allow_blank=True, max_length=100, required=False)
>>> s.is_valid()
True
>>> s.validated_data?? #返回ordereddict
OrderedDict([('first_name', 'chai'), ('last_name', 'jowin'), ('email', 'jowin@chai.com')])
>>> s.save()
<Author: chai jowin>
?
>>> Author.objects.all()
<QuerySet [<Author: chai jowin>, <Author: dsfdfd sfdsfdsf>, <Author: chai jowin>]>
>>> s = AuthorSerializer(Author.objects.all(), many=True)?? #序列化多個對象時要加many=True,調用many_init()
>>> s.data
[OrderedDict([('id', 1), ('first_name', 'chai'), ('last_name', 'jowin'), ('email', 'jowin@chai.com')]), OrderedDict([('id', 2), ('first_name', 'dsfdfd'), ('la
st_name', 'sfdsfdsf'), ('email', 'dsfdsf@dsfdsf.com')]), OrderedDict([('id', 3), ('first_name', 'chai'), ('last_name', 'jowin'), ('email', 'jowin@chai.com')])
]
?
?
?
rest_framework.serializers.ModelSerializer同django.forms.ModelForm;
?
?
class AuthorSerializer(serializers.ModelSerializer):
??? class Meta:
??????? model = Author
??????? fields = ['id', 'first_name', 'last_name', 'email']
?
?
?
from django.http import HttpResponse
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from .serializer import AuthorSerializer
from .models import Author
from django.views.decorators.csrf import csrf_exempt
?
class JSONResponse(HttpResponse):?? #可用django.http.JsonResponse
??? def __init__(self, data, **kwargs):
??????? content = JSONRenderer().render(data)
??????? kwargs['content_type'] = 'application/json'
??????? super(JSONResponse, self).__init__(content, **kwargs)?? #同super().__init__(content, **kwargs)
?
@csrf_exempt
def author_list(request):
??? if request.method == 'GET':
??????? authors = Author.objects.all()
??????? serializer = AuthorSerializer(authors, many=True)
??????? return JsonResponse(serializer.data, safe=False)?? # 默認safe=True,In order to allow non-dict objects to be serialized set the safe parameter to False.
?
??? elif request.method == 'POST':
??????? data = JSONParser().parse(request)
??????? serializer = AuthorSerializer(data=data)
??????? if serializer.is_valid():
??????????? serializer.save()
??????????? return JSONResponse(serializer.data, status=201)
??? ????return JSONResponse(serializer.errors, status=400)
?
@csrf_exempt
def author_detail(request, pk):
??? try:
??????? author = Author.objects.get(pk=pk)
??? except Author.DoesNotExist:
??????? return JSONResponse(status=404)
?
??? if request.method == 'GET':
??????? serializer = AuthorSerializer(author)
??????? return JSONResponse(serializer.data)
?
??? elif request.method == 'PUT':
??????? data = JSONParser().parse(request)
??????? serializer = AuthorSerializer(author, data=data)
??????? if serializer.is_valid():
??????????? serializer.save()
??????????? return JSONResponse(serializer.data)
??????? return JSONResponse(serializer.errors, status=400)
?
??? elif request.method == 'DELETE':
??????? author.delete()
??????? return JSONResponse('', status=204)
?
?
??? url(r'^authors/$', api.author_list, name='author_list'),
??? url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),
?
?
?
request.POST? # Only handles form data.? Only works for 'POST' method.
request.data? # Handles arbitrary data.? Works for 'POST', 'PUT' and 'PATCH' methods.
?
?
return Response(data)? # Renders to content type as requested by the client.根據客戶端的請求渲染內容類型
?
?
?
The @api_view decorator for working with function based views.
The APIView class for working with class-based views.?? #同django.views.View
?
例,@api_view:
@api_view(['GET', 'POST'])?? #只作為接口使用,用browser訪問報WrappedAttributeError,'CSRFCheck' object has no attribute 'process_request'
@csrf_exempt
def author_list(request):
??? if request.method == 'GET':
??????? authors = Author.objects.all()
??????? serializer = AuthorSerializer(authors, many=True)
??????? # return JSONResponse(serializer.data)
??????? # return JsonResponse(serializer.data, safe=False)
??????? return Response(serializer.data)
?
??? elif request.method == 'POST':
??????? data = JSONParser().parse(request)
??????? serializer = AuthorSerializer(data=data)
??????? if serializer.is_valid():
??????????? serializer.save()
??????????? # return JsonResponse(serializer.data, status=201)
??????????? return Response(serializer.data, status=201)
??????? # return JsonResponse(serializer.errors, status=400)
??????? return Response(serializer.errors, status=400)
?
用postman測GET和POST;
?
?
?
?
from rest_framework.views import APIView
from rest_framework import status
from django.http import Http404
?
class AuthorList(APIView):
??? def get(self, request, format=None):
??????? authors = Author.objects.all()
??????? serializer = AuthorSerializer(authors, many=True)
??????? return Response(serializer.data)
?
??? def post(self, request, format=None):
??????? serializer = AuthorSerializer(data=request.data)
??????? if serializer.is_valid():
??????????? serializer.save()
??????????? return Response(serializer.data, status=status.HTTP_201_CREATED)
??????? return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
?
class AuthorDetail(APIView):
??? def get_object(self, pk):
??????? try:
??????????? return Author.objects.get(pk=pk)
??????? except Author.DoesNotExist:
??????????? return Http404
?
??? def get(self, request, pk, format=None):
??????? author = self.get_object(pk)
??????? serializer = AuthorSerializer(author)
??????? return Response(serializer.data)
?
??? def put(self, request, pk, format=None):
??????? author = self.get_object(pk)
??????? serializer = AuthorSerializer(author, data=request.data)
??????? if serializer.is_valid():
??????????? serializer.save()
?? ?????????return Response(serializer.data)
??????? return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
?
??? def delete(self, request, pk, format=None):
??????? author = self.get_object(pk)
??????? author.delete()
??????? return Response(status=status.HTTP_204_NO_CONTENT)
?
?
??? # url(r'^authors/$', api.author_list, name='author_list'),
??? url(r'^authors/$', AuthorList.as_view()),
??? # url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),
??? url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetail.as_view()),
?
?
?
from rest_framework import mixins
from rest_framework import generics
?
class AuthorList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
?
??? def get(self, request, *args, **kwargs):
??????? return self.list(request, *args, **kwargs)
?
??? def post(self, request, *args, **kwargs):
??????? return self.create(request, *args, **kwargs)
?
class AuthorDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
?
??? def get(self, request, *args, **kwargs):
??????? return self.retrieve(request, *args, **kwargs)
?
??? def put(self, request, *args, **kwargs):
??????? return self.update(request, *args, **kwargs)
?
??? def delete(self, request, *args, **kwargs):
??????? return self.destroy(request, *args, **kwargs)
?
?
?
?
from rest_framework import generics
?
class AuthorList(generics.ListCreateAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
?
class AuthorDetail(generics.RetrieveUpdateDestroyAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
?
postman測試時,PUT方法注意要用JSON;
?
?
REST_FRAMEWORK = {
??? # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
??? 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
??? "PAGE_SIZE": 2,
?
?
django支持認證方式:
Basic,默認;
Session;
Token;
自定義認證;
?
默認用Basic認證,輸入Username和Password,會自動生成到Headers中,用base64加密;
?
?
例,使用token認證:
INSTALLED_APPS = [
??? 'rest_framework.authtoken',
?
REST_FRAMEWORK = {
??? "DEFAULT_AUTHENTICATION_CLASSES": (
??????? # 'rest_framework.authentication.BasicAuthentication',
??????? # 'rest_framework.authentication.SessionAuthentication',
??????? 'rest_framework.authentication.TokenAuthentication',
??? )
}
?
(webproject) C:\webproject\mysite>python manage.py makemigrations
(webproject) C:\webproject\mysite>python manage.py migrate
?
>>> from django.contrib.auth.models import User
>>> from rest_framework.authtoken.models import Token
>>> t = Token.objects.create(user=User.objects.get(id=1))
>>> t.key
'219c0ec96617256b93b36d0ab95b70e7c893ac1b'
?
?
?
例,用session認證:
KEY中Cookie,VALUE中粘貼網頁中Network中csrftoken;
?
?
?
https://www.django-rest-framework.org/api-guide/permissions/#api-reference
?
rest_framework內置權限:
AllowAny
IsAuthenticated
IsAdminUser
IsAuthenticatedOrReadOnly
DjangoModelPermissions
DjangoModelPermissionsOrAnonReadOnly
DjangoObjectPermissions
?
REST_FRAMEWORK = {
??? "PAGE_SIZE": 1,
??? "DEFAULT_AUTHENTICATION_CLASSES": (
??????? # 'rest_framework.authentication.BasicAuthentication',
??????? # 'rest_framework.authentication.SessionAuthentication',
??????? 'rest_framework.authentication.TokenAuthentication',
??????? 'rest_framework.permissions.IsAuthenticated',?? #全局配置默認權限
??? )
}
?
?
例,view中使用權限控制:
from rest_framework import generics
from rest_framework import permissions
?
class AuthorList(generics.ListCreateAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
??? permission_classes = (permissions.IsAuthenticated,)?? #多個是and的關系
?
?
例,自定義權限:
from rest_framework import generics
from rest_framework import permissions
?
class IsSuperUser(permissions.BasePermission):?? #繼承permissions.BasePermission,重寫has_permission()
??? def has_permission(self, request, view):
??????? return request.user.is_superuser()
?
class AuthorList(generics.ListCreateAPIView):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
??? # permission_classes = (permissions.IsAuthenticated,)
??? permission_classes = (IsSuperUser,)
?
?
?
ViewSet與View,不同之處在于ViewSet提供read或update之類的操作,而不是get或put等方法處理程序;當它被實例化成一組視圖的時候,通過使用Router類來處理自己定義的url;
?
?
例:
from rest_framework import viewsets
?
class AuthorViewSet(viewsets.ReadOnlyModelViewSet):?? #僅提供list和detail操作
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
??? # permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
?
?
例:
from rest_framework import viewsets
?
class AuthorViewSet(viewsets.ModelViewSet):?? #提供list|create|retrieve|update|destroy
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
# permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
?
?
author_list = AuthorViewSet.as_view({
??? 'get': 'list',
??? 'post': 'create'
})
?
author_detail = AuthorViewSet.as_view({
??? 'get': 'retrieve',
??? 'put': 'update',
??? 'pathch': 'partial_update',
??? 'delete': 'destroy',
})
?
??? # url(r'^authors/$', api.author_list, name='author_list'),
??? # url(r'^authors/$', AuthorList.as_view()),
??? url(r'^authors/$', author_list, name='author-list'),
??? # url(r'^authors/(?P<pk>[0-9]+)/$', api.author_detail, name='author_detail'),
??? # url(r'^authors/(?P<pk>[0-9]+)/$', AuthorDetail.as_view()),
??? url(r'^authors/(?P<pk>[0-9]+)/$', author_detail, name='author-detail'),
?
?
例,使用routers:
from rest_framework import viewsets
?
class AuthorViewSet(viewsets.ModelViewSet):
??? queryset = Author.objects.all()
??? serializer_class = AuthorSerializer
# permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
?
?
router = DefaultRouter()
router.register(r'authors', AuthorViewSet)
?
?
urlpatterns = [
???????? ……
]
?
urlpatterns += router.urls?? #方式1
# urlpatterns += [?? #方式2
#???? url(r'^', include(router.urls)),
# ]
?
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。