https://www.django-rest-framework.org/
https://q1mi.github.io/Django-REST-framework-documentation/
DRF / Django REST framework is a powerful and flexible toolkit for building Web APIs.
Some reasons you might want to use REST framework:
- The Web browsable API is a huge usability win for your developers.
- Authentication policies including packages for OAuth1a and OAuth2.
- Serialization that supports both ORM and non-ORM data sources.
- Customizable all the way down - just use regular function-based views if you don't need the more powerful features.
- Extensive documentation, and great community support.
- Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite.
1. 序列化结构化数据 / Serializer
2. 服务化接口和界面 RestAPI Viewset
3. 路由配置 Routers
4. 授权协议 JWT/OAuth
5. 数据关联增强 Relationship
...
Preparation
代码语言:shell复制# ============================================================ #
# DRF DjangoRestFramework #
# ============================================================ #
pip install django
pip install djangorestframework
django-admin startproject xx
django-admin startapp xxx
>>> coding >>>
python manage.py migrate
python manage.py makemigrations xxx
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Helloworld
代码语言:python代码运行次数:0复制# ============================================================ #
# Helloworld (serializers views urls settings) #
# ============================================================ #
## serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url','username','email','groups')
## views.py
from django.contrib.auth.models import User
from rest_framework import viewsets
from user.serializers import UserSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
## urls.py
from django.conf.urls import url, include
from rest_framework import routers
from user import views
router = routers.DefaultRouter()
router.register(r'users',views.UserViewSet)
urlpatterns = [
url(r'^',include(router.urls)),
url(r'^api-auth/',include('rest_framework.urls',namespace='rest_framework'))
]
## settings.py
'rest_framework',
'user',
More(Serializer JSONResponse/APIView/CBV/mixin/generics) = Ready
代码语言:python代码运行次数:0复制# ------------------------------------------------------------ #
# models.py
# ------------------------------------------------------------ #
# basic django models for ORM
# ------------------------------------------------------------ #
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
class Meta: ordering = ('created',)
两类序列化方法:
代码语言:python代码运行次数:0复制# ------------------------------------------------------------ #
# serializer.py
# ------------------------------------------------------------ #
# serializer refactor A general serializer
# ------------------------------------------------------------ #
from rest_framework import serializers
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES
class SnippetSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
code = serializers.CharField(style={'base_template':'textarea.html'})
linenos = serializers.BooleanField(required=True)
language =serializers.ChoiceField(choices=LANGUAGE_CHOICES, default='python')
style = serializers.ChoiceField(choices=STYLE_CHOICES, default='friendly')
def create(self, validated_data):
return Snippet.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.code = validated_data.get('code', instance.code)
instance.linenos = validated_data.get('linenos', instance.linenos)
instance.language = validated_data.get('language', instance.language)
instance.style = validated_data.get('style', instance.style)
instance.save()
return instance
# ------------------------------------------------------------ #
# serializer refactor B ModelSerializer
# ------------------------------------------------------------ #
from rest_framework import serializers
from snippets.models import Snippet
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
urls
代码语言:python代码运行次数:0复制# ------------------------------------------------------------ #
# url.py
# ------------------------------------------------------------ #
# url namespace
# ------------------------------------------------------------ #
from rest_framework.urlpatterns import format_suffix_patterns
from django.conf.urls import url, include
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.SnippetList.as_view()),
url(r'^snippets/(?P<pk>[0-9] )/$',views.SnippetDetail.as_view()),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
urlpatterns = format_suffix_patterns(urlpatterns)
views *5
代码语言:python代码运行次数:0复制# ------------------------------------------------------------ #
# views.py
# ------------------------------------------------------------ #
# views refactor 1 JSON parse
# ------------------------------------------------------------ #
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
class JSONResponse(HttpResponse):
def __init__(self, data, **kwargs):
content = JSONRenderer().render(data)
kwargs['content_type'] = 'application/json'
super(JSONResponse, self).__init__(content, **kwargs)
@csrf_exempt
def snippet_list(request):
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return JSONResponse(serializer.data)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = SnippetSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data, status=201)
return JSONResponse(serializer.errors, status=400)
@csrf_exempt
def snippet_detail(request, pk):
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return HttpResponse(status=404)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return JSONResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data)
return JSONResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
snippet.delete()
return HttpResponse(status=204)
# ------------------------------------------------------------ #
# views refactor 2 Functional Views / @api_view Response
# ------------------------------------------------------------ #
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
@api_view(['GET','POST'])
def snippet_list(request, format=None):
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = SnippetSerializer(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)
@api_view(['GET','PUT','DELETE'])
def snippet_detail(request, pk, format=None):
try: snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_404_BAD_REQUEST)
elif request.method == 'DELETE':
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
# ------------------------------------------------------------ #
# views refactor 3 ClassBasedViews/CBV
# ------------------------------------------------------------ #
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
def get(self, request, fromat=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(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 SnippetDetail(APIView):
def get_object(self, pk):
try: return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist: raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, 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):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
# ------------------------------------------------------------ #
# views refactor 4 mixins
# ------------------------------------------------------------ #
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self,request,*args,**kwargs): return self.list(request,*args,**kwargs)
def post(self,*args,**kwargs):return self.create(request,*args,**kwargs)
class SnippetDetail( mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView ):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
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.destory(request,*args,**kwargs)
# ------------------------------------------------------------ #
# ListModelMixin
# class ListModelMixin(object):
# """
# List a queryset.
# """
# def list(self, request, *args, **kwargs):
# queryset = self.filter_queryset(self.get_queryset())
# page = self.paginate_queryset(queryset)
# if page is not None:
# serializer = self.get_serializer(page, many=True)
# return self.get_paginated_response(serializer.data)
#
# serializer = self.get_serializer(queryset, many=True)
# return Response(serializer.data)
# ------------------------------------------------------------ #
# views refactor 5 mixed-in
# ------------------------------------------------------------ #
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
More - Authentication/Identification/认证
代码语言:python代码运行次数:0复制# ============================================================ #
# Authentication #
# ============================================================ #
# models.py add user
# ------------------------------------------------------------ #
from django.db import models
#
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight
#
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
#
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
#
owner = models.ForeignKey('auth.User',related_name='snippets',on_delete=models.CASCADE)
highlighted = models.TextField()
#
class Meta: ordering = ('created',)
#
def save(self, *args, **kwargs):
lexer = get_lexer_by_name(self.language)
linenos = self.linenos and 'table' or False
options = self.title and {'title': self.title} or {}
formatter = HtmlFormatter(style=self.style, linenos= linenos, full= True, **options)
self.highlighted = highlight(self.code, lexer, formatter)
super(Snippet, self).save(*args,**kwargs)
# ------------------------------------------------------------ #
# serializers.py user serializer
# ------------------------------------------------------------ #
from rest_framework import serializers
from snippets.models import Snippet
from django.contrib.auth.models import User
#
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Snippet
fields = ('id', 'title', 'code', 'linenos', 'language', 'style', 'owner')
#
class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
class Meta:
model = User
fields = ('id', 'username', 'snippets')
# ------------------------------------------------------------ #
# permissions.py
# ------------------------------------------------------------ #
from rest_framework import permissions
#
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS: return True # GET,HEAD,OPTIONS -> Okay
return obj.owner == request.user
# ------------------------------------------------------------ #
# views.py user list and detail
# ------------------------------------------------------------ #
from rest_framework import generics
#
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
#
from django.contrib.auth.models import User
from snippets.serializers import UserSerializer
#
from rest_framework import permissions
from snippets.permissions import IsOwnerOrReadOnly
#
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
#
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)
#
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
#
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
# ------------------------------------------------------------ #
# urls.py
# ------------------------------------------------------------ #
from rest_framework.urlpatterns import format_suffix_patterns
from django.conf.urls import url, include
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.SnippetList.as_view()),
url(r'^snippets/(?P<pk>[0-9] )/$',views.SnippetDetail.as_view()),
url(r'^users/$',views.UserList.as_view()),
url(r'^users/(?P<pk>[0-9] )/$',views.UserDetail.as_view()),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]
urlpatterns = format_suffix_patterns(urlpatterns)
最后带上viewsets和router
代码语言:python代码运行次数:0复制# ============================================================ #
# Final (serializers viewsets routers authentication)#
# ============================================================ #
# models.py
# ------------------------------------------------------------ #
from django.db import models
#
from pygments.lexers import get_all_lexers, get_lexer_by_name
from pygments.styles import get_all_styles
from pygments.formatters.html import HtmlFormatter
from pygments import highlight
#
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
#
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
linenos = models.BooleanField(default=False)
code = models.TextField()
language = models.CharField(choices=LANGUAGE_CHOICES,default='Python',max_length=100)
title = models.CharField(max_length=100,blank=True,default='')
style = models.CharField(choices=STYLE_CHOICES,default='friendly',max_length=100)
owner = models.ForeignKey('auth.User',related_name='snippets',on_delete=models.CASCADE)
highlighted = models.TextField()
class Meta: ordering = ('created',)
def save(self, *args, **kwargs):
lexer = get_lexer_by_name(self.language)
linenos = self.linenos and 'table' or False
options = self.title and {'title': self.title} or {}
formatter = HtmlFormatter(style=self.style,linenos=linenos,full=True,**options)
super(Snippet,self).save(*args,**kwargs)
# ------------------------------------------------------------ #
# serializers.py
# ------------------------------------------------------------ #
from rest_framework import serializers
from snippets.models import Snippet
from django.contrib.auth.models import User
#
class SnippetSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight',format='html')
class Meta:
model = Snippet
fields = ('url','id','highlight','title','code','linenos','language','style','owner')
#
class UserSerializer(serializers.HyperlinkedModelSerializer):
snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)
class Meta:
model = User
fields = ('url','id','username','snippets')
# ------------------------------------------------------------ #
# permissions.py
# ------------------------------------------------------------ #
from rest_framework import permissions
#
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self,request,view,obj):
if request.method in permissions.SAFE_METHODS: return True
return obj.owner == request.user
# ------------------------------------------------------------ #
# views.py
# ------------------------------------------------------------ #
from rest_framework import permissions
from rest_framework import renderers
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
#
from django.contrib.auth.models import User
#
from snippets.api.serializers import SnippetSerializer, UserSerializer
from snippets.api.permissions import IsOwnerOrReadOnly
from snippets.models import Snippet
#
class SnippetViewSet(viewsets.ModelViewSet):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,)
#
@action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
def highlight(self, request, *args, **kwargs):
snippet = self.get_object()
return Response(snippet.highlighted)
#
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
#
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# ------------------------------------------------------------ #
# urls.py
# ------------------------------------------------------------ #
from rest_framework.routers import DefaultRouter
from django.urls import path, include
from snippets import views
#
router = DefaultRouter()
router.register(r'snippets',views.SnippetViewSet)
router.register(r'users',views.UserViewSet)
#
urlpatterns = [
path('', include(router.urls)),
path(r'^api-auth/',include('rest_framework.urls',namespace='rest_framework')),
]
1、基本视图类-类基础视图(APIView)
不同于django常规的view类,优点:
代码语言:javascript复制* 提供了更好用的request对象,不同于普通的django HttpRequest更好用。
* 封装了Response对象,代替了原有的django HttpResponse,视图将管理内容协商并设置正确的渲染器的响应。
* 任何APIException异常将会被捕捉,并做适当的响应。
* 传入的请求将身份验证和适当的权限和节流检查将之前运行调度请求处理程序的方法。
1) API策略属性
以下的API策略属性应用于APIView,控制视图的策略:
代码语言:javascript复制renderer_classes: 渲染器类
parser_classes: 解释器类
authentication_classes: 权限类
throttle_classes:节流类
permission_classes: 权限类
content_negotiation_class: 内容协商类
2)API 策略方法
以下的策略方法用在API的策略,通常不用重写它:
代码语言:javascript复制get_renderers(self): 获取渲染器方法
get_parsers(self): 获取解释器方法
get_authenticators(self): 获取认证方法
get_throttles(self): 获取节流方法
get_permissions(self): 获取权限方法
get_content_negotiator(self): 获取内容协商方法
3)API策略实施方法
下列方法之前被称为调度处理程序方法:
代码语言:javascript复制check_permissions(self, request): 检查权限
check_throttles(self, request): 检查节流
check_content_negotiation(self, request, force=False): 检查内容协商
4)调度方法
这些执行任何操作,需要发生之前或之后调用处理程序方法等.
代码语言:javascript复制initial(self, request, *args, **kwargs):
执行任何操作,需要发生在处理程序方法之前被调用。这个方法是用来执行权限和节流,并执行内容协商。
handle_exception(self, exc):
抛出的任何异常处理程序方法将被传递给这个方法,而返回响应实例,或者re-raises异常。
initialize_request(self, request, *args, **kwargs):
确保请求对象传递给处理程序方法是request的一个实例,而不是django的HttpRequest
finalize_response(self, request, response, *args, **kwargs):
确保任何响应处理程序方法返回的对象将被呈现到正确的内容类型
2、基本视图类-函数基础视图(@api_view())
一种函数基础视图来装饰django的普通视图,我们同样可以使用request来接受请求和response响应。
1)api_view()使用方法
这个视图将使用默认渲染器、解析器、身份验证设置中指定的类等。
通常默认只有GET方法,其他请求方法会报405错误,我们可以手动添加方法为这装饰器指定request方法。
2)API策略装饰器
很多附加的装饰器,我们可以添加到@api_view()后面,例如要加入一个节流@throttle_classes来确保特定用户每天只能一次通过这个视图
代码语言:python代码运行次数:0复制@renderer_classes(…)
@parser_classes(…)
@authentication_classes(…)
@throttle_classes(…)
@permission_classes(…)
3、通用视图(Generic views)
基于类视图的主要好处之一是他们允许编写可重用的行为.
REST框架提供的通用视图允许快速构建API观点紧密地映射到数据库模型,如果通用视图不适合的需要API,
可以使用常规APIView类,或重用mixin和基类使用的通用视图来组成自己的组可重用通用视图。
通用视图可以设置一些类属性在通用视图内,也可以根据特殊要写重写它的内部视图方法
使用.as_views()来转换成视图函数
代码语言:python代码运行次数:0复制url(r’^/users/’, ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name=’user-list’)
4、通用API视图(GenericAPIView)
GenericAPIView继承了DRF的APIView类,为list和detail视图增加了一些一般需求行为方法(提供queryset)。
1)属性
基本属性:
代码语言:html复制queryset: 用于返回query对象集合,也可以使用get_queryset()方法。
serializer_class: 序列化器类,应该用于输入进行验证和反序列化,并用于序列化输出。
通常情况下,你必须设置这个属性,或重写get_serializer_class()方法。
lookup_field: 模型的字段应该用于执行对象查找个别的模型实例
lookup_url_kwarg:URL应该用于对象查找关键字参数
分页属性:
pagination_class: 用于返回一个分页列表视图的分页类,默认与settings中设置的DEFAULT_PAGINATION_CLASS 值相同,设置分页数过滤器属性:
代码语言:javascript复制'rest_framework.pagination.PageNumberPagination’
filter_backends: 过滤queryset的类列表,和在settings中设置DEFAULT_FILTER_BACKENDS 一样
2)方法
基本方法:
get_queryset(): 返回queryset。(详情见官网http://www.django-rest-framework.org/api-guide/generic-views/)
get_object():获取某一个具体的model实例对象。
保存与删除挂钩方法:
以下方法是mixins类提供,提供简单的对象保存和删除的行为重写:
代码语言:javascript复制perform_create(self, serializer): CreateModelMixin 保存对象时候会被调用
perform_update(self, serializer):UpdateModelMixin 更新对象时候会被调用
perform_destroy(self, instance): DestoryModelMixin 删除对象时候会被调用
3)、Mixins
mixin类提供用于提供基础视图的操作行为。注意,mixin类提供操作方法而不是定义处理程序方法,比如. get()和. post(),直接。这允许更灵活的组合的行为。
通过rest_framework.mixins引用。
代码语言:javascript复制ListModelMixin:提供list方法,列出queryset
CreateModelMixin: 提供create方法,创建和保存一个Model对象
RetrieveModelMixin:提供retrieve方法,检索一个存在的model对象
UpdateModelMixin: 提供Update方法,更改一个模型对象
DestroyModelMixin:提供destroy方法,删除一个模型对象
4)Generic
代码语言:text复制Generic通用视图类提供具体操作的通用视图类,
可以理解为Generic.GenericAPIView和mixin类的合体,通过rest_framework.generic.调用
.CreateAPIView:
创建一个模型实例,提供post方法的处理器,继承于:GenericAPIView,CreateModelMixin
.ListAPIView:
模型实例的集合,提供get方法处理器,
继承于:GenericAPIView,ListModelMixin
.RetrieveAPIView:
一个模型实例,提供get方法处理器,
继承于:GenericAPIView,RetrieveModelMixin
.DestoryAPIView:
删除一个模型实例,提供delete方法处理器,
继承于:GenericAPIView,DestroyModelMixin
.UpdateAPIView:
修改模型实例,提供put和patch方法处理器,
继承于:GenericAPIView,UpdateModelMixin
.ListCreateAPIView:
创建和展示一个模型实例集合,提供get和post处理器,
继承于:GenericAPIView,ListModelMixin,CreateModelMixin
.RetrieveUpdateAPIView:
读和改一个模型实例,提供get,put,patch处理器,
继承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin
.RetrieveDestoryAPIView:
读和删除一个模型实例,提供get和delete处理器,
继承于:GenericAPIView,RetrieveModelMixin,DestroyModelMixin
.RetrieveUpdateDestroyAPIView:
读、改和删一个模型实例,get, put, patch,delete处理器,
继承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixi
5、视图集合ViewSets
允许将一组相关的逻辑视图在一个类,ViewSet类是一个简单类型的基于类的观点,没有提供任何方法处理程序如.get()或. post(), 而代替提供方法比如.list()和create()。
代码语言:python代码运行次数:0复制# 需要为两个GET请求分开绑定视图:
user_list = UserViewSet.as_view({“GET”:’list’})
user_detail = UserViewSet.as_view({‘GET’:’retrieve’})
# 或者通过url配置:
from myapp.views import UserViewSet
from rest_framework.routers import DefaultRoute
router = DefaultRouter()
router.register(r’users’, UserViewSet)
urlpatterns = router.urls
# 其他路由函数方法:
# list/create/retrieve/update/partial_update/destroy(self, request, pk=None)/@detail_route/@list_route
@detail_route(methods=[‘post’], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
pass
可以通过访问^users/{pk}/set_password/$来访问改视图
ViewSets的API参考
.ViewSet:
继承了APIView,可以使用一些标准的属性例如permission_class,authentication_classes去对视图做一些策略。
ViewSet同样不提供具体行为方法的实现,可以重写和定义一些请求处理方法。
而代替了原来APIVIew的POST,GET等方法,取而代之的是list,create等方法。
.GenericViewSet:
继承了GenericAPIView,提供了默认的get_queryset()和get_object()等方法来获取model数据,但不提供任何请求处理方法。
.ModelViewSet:
继承了GenericAPIView,增加了一些请求处理方法,如list(), retrieve(),create()等。
代码语言:python代码运行次数:0复制class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerialize
permissions_classes = [IsAccountAdminOrReadOnly]
.ReadOnlyModelViewSet:
继承了GenericAPIView,只增加了只读的请求处理方法list()和retrieve()
自定义View类:只需要继承GenericAPIView, 增加mixins的相关处理方法。
代码语言:python代码运行次数:0复制class CreatListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
View.GenericViewSet):
pass