简介
为什么要使用REST framework?
Django REST framework 是一个强大且灵活的工具包,用以构建Web APIs。
- 在线可视的API,对于赢得你的开发者们十分有用
- 验证策略涵盖了OAuth1a和OAuth2
- 同时支持ORM和非ORM数据源的序列化
- 可以配置各个环节,若无需更多强大的特性,使用一般基于类(function-based)的视图(views)即可
- 大量的文档,强力的社区支持
- 大公司如同Mozilla和Eventbrite,也是忠实的使用者
配置要求
REST framework 有以下的要求:
- Python (2.7, 3.2, 3.3, 3.4, 3.5)
- Django (1.7+, 1.8, 1.9)
下面是可选的包:
- Markdown (2.1.0+) - Markdown为可视化 API 提供了支持.
- django-filter (0.9.2+) - 过滤支持.
- django-crispy-forms - 为过滤,提供了改良的HTML呈现.
- django-guardian (1.1.1+) - 对象层面的权限支持.
安装与配置
安装
1
2
3
|
pip install djangorestframework pip install markdown # 可选依赖包
pip install django - filter # 可选依赖包
|
配置
1
2
3
4
5
6
7
8
9
10
|
INSTALLED_APPS = (
...
'rest_framework' ,
) REST_FRAMEWORK = {
# 编码格式
'UNICODE_JSON' : False ,
} |
基本使用方法
models.py
1
2
3
4
5
6
7
|
from django.db import models
class Author(models.Model):
name = models.CharField(max_length = 32 )
age = models.IntegerField()
def __str__( self ):
return self .name
|
urls.py
1
2
3
4
5
6
7
8
|
from django.conf.urls import url
from django.contrib import admin
from rest_demoimport views
urlpatterns = [
url(r '^admin/' , admin.site.urls),
url(r '^authors/$' , views.AuthorsView.as_view()),
url(r '^authors/(\d+)/$' , views.AuthorsDetailView.as_view()),
] |
serializer.py
1
2
3
4
5
6
7
|
from rest_framework import serializers
from rest_demo import models
class AuthorModelSerializers(serializers.ModelSerializer):
class Meta:
model = models.Author
fields = '__all__'
|
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
from rest_demo import serializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_demo import models
class AuthorsView(APIView):
def get( self ,request):
'''
查询所有作者
:param request:
:return:
'''
author_list = models.Author.objects. all ()
auts = serializer.AuthorModelSerializers(author_list,many = True )
return Response(auts.data)
def post( self ,request):
'''
添加作者
:param request:
:return:
'''
auts = serializer.AuthorModelSerializers(data = request.data)
if auts.is_valid():
auts.save()
return Response(auts.data)
return Response(auts.errors)
class AuthorsDetailView(APIView):
def get( self ,request, id ):
'''
查询单条作者
:param request:
:param id:
:return:
'''
author = models.Author.objects. filter (pk = id ).first()
auts = serializer.AuthorModelSerializers(author)
return Response(auts.data)
def put( self ,request, id ):
'''
修改单条作者
:param request:
:param id:
:return:
'''
author = models.Author.objects. filter (pk = id ).first()
auts = serializer.AuthorModelSerializers(instance = author,data = request.data)
if auts.is_valid():
auts.save()
return Response(auts.data)
return Response(auts.errors)
def delete( self ,request, id ):
'''
删除单条作者
:param request:
:param id:
:return:
'''
models.Author.objects. filter (pk = id ).delete()
return Response()
|
封装
继承mixin包下面的类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
from rest_framework import mixins
from rest_framework import generics
class PublishView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView):
queryset = models.Publish.objects. all ()
serializer_class = serializer.PublishSerializers
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 PublishDetailView(mixins.RetrieveModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,generics.GenericAPIView):
queryset = models.Publish.objects. all ()
serializer_class = serializer.PublishSerializers
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)
|
这个时候,我们只需要提供queryset和serializer_class两个参数配置,mixin包下面的类会帮我们处理数据,我们调用对应的方法并且将其返回值返回即可,
但是需要注意的是,如果使用此方法,urls.py的url对应的id要命名为pk,如下:
1
2
|
url(r '^publishes/$' , views.PublishView.as_view()),
url(r '^publishes/(?P<pk>\d+)/$' , views.PublishDetailView.as_view()),
|
但是,即使我们用了这种封装,很多代码还是有重复的,所有,rest_framework又给我们做了一层封装
继承generices包下面的类
只需要改变一下XXXView类的继承类
1
2
3
4
5
6
7
8
9
|
from rest_framework import generics
class PublishView(generics.ListCreateAPIView):
queryset = models.Publish.objects. all ()
serializer_class = serializer.PublishSerializers
class PublishDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.Publish.objects. all ()
serializer_class = serializer.PublishSerializers
|
这样,代码就清晰很多了,但是,这种方法依然是将一个model表分成两个视图,那,有没有一种方法能将他们合并在一起呢?
继承viewsets包下的ModelViewSet
urls.py
1
2
3
4
5
6
7
|
url(r '^books/$' , views.BookViewSet.as_view({ "get" : "list" , "post" : "create" }),name = "book_list" ),
url(r '^books/(?P<pk>\d+)$' , views.BookViewSet.as_view({
'get' : 'retrieve' ,
'put' : 'update' ,
'patch' : 'partial_update' ,
'delete' : 'destroy'
}),name = "book_detail" ),
|
views.py
1
2
3
4
|
from rest_framework import viewsets
class BookViewSet(viewsets.ModelViewSet):
queryset = models.Book.objects. all ()
serializer_class = serializer.BookSerializers
|
示例
INSTALLED_APPS = [
....
'rest_framework',
]
settings.py
from django.db import models class Book(models.Model):
title=models.CharField(max_length=32)
price=models.IntegerField()
pub_date=models.DateField()
publish=models.ForeignKey("Publish",on_delete=models.CASCADE)
authors=models.ManyToManyField("Author")
def __str__(self):
return self.title class Publish(models.Model):
name=models.CharField(max_length=32)
email=models.EmailField()
def __str__(self):
return self.name class Author(models.Model):
name=models.CharField(max_length=32)
age=models.IntegerField()
def __str__(self):
return self.name
models.py
########### urls.py ##############
from django.contrib import admin
from django.urls import path,re_path,include urlpatterns = [
re_path("testrestfulframework/",include("testrestfulframework.urls")),
] ########### testrestfulframework/urls.py ############## from django.contrib import admin
from django.urls import path,re_path,include
from testrestfulframework import views urlpatterns = [
re_path(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
re_path(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
re_path(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
re_path(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
re_path(r'^authors/$', views.AuthorViewSet.as_view(), name="authorlist"),
re_path(r'^authors/(?P<pk>\d+)$', views.AuthorDetailViewSet.as_view(), name="author_detail"), # re_path(r'^books/$', views.BookViewSet.as_view(**{"get":"list","post":"create"}),name="book_list"),
# re_path(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view(**{'get': 'retrieve','put': 'update','patch': 'partial_update','delete': 'destroy'}),name="book_detail"),
]
urls.py
示例0 views的不同写法(以下三种写法等价)
from rest_framework.views import APIView
from rest_framework.response import Response
from django.shortcuts import HttpResponse
from rest_framework import mixins from .models import *
from rest_framework import generics
from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# depth=1 class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
bs=BookSerializers(book_list,many=True,context={"request":request})
return Response(bs.data) def post(self, request, *args, **kwargs): bs = BookSerializers(data=request.data, many=False,context={"request":request})
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class BookDetailViewSet(APIView): def get(self,request,*args,**kwargs):
book_obj=Book.objects.filter(pk=kwargs["pk"]).first()
bs=BookSerializers(book_obj,context={"request":request})
return Response(bs.data) def put(self,request,*args,**kwargs):
book_obj=Book.objects.filter(pk=kwargs["pk"]).first()
bs=BookSerializers(book_obj,data=request.data,context={"request":request})
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) def patch(self,request,*args,**kwargs):
book_obj=Book.objects.filter(pk=kwargs["pk"]).first()
bs=BookSerializers(book_obj,data=request.data,context={"request":request},partial="partial")
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) def delete(self,request,*args,**kwargs):
# 这里是自己写的,没找到网上相关
book_obj=Book.objects.filter(pk=kwargs["pk"]).first() if book_obj:
book_obj.delete()
return Response("delete done")
else:
return Response("no such data")
一般写法
from .models import *
from rest_framework import mixins
from rest_framework import generics
from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# depth=1 class BookViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView): queryset = Book.objects.all()
serializer_class = BookSerializers 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 BookDetailViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers 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) def patch(self,request,*args,**kwargs):
return self.partial_update(request,*args,**kwargs)
mixins类
from .models import *
from rest_framework import generics
from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# depth=1 class BookViewSet(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers
纯generics类
以上均试验成功。
示例1 get请求
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers class BookSerializers(serializers.Serializer):
title=serializers.CharField(max_length=32)
price=serializers.IntegerField()
pub_date=serializers.DateField()
publish=serializers.CharField(source="publish.name")
#authors=serializers.CharField(source="authors.all")
authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for author in obj.authors.all():
# temp.append(author.name)
# temp.append((author.name,author.age,author.id))
temp.append({"id":author.id,"name":author.name,"age":author.age})
return temp class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
# 序列化方式1:
# from django.forms.models import model_to_dict
# data=[]
# for obj in book_list:
# data.append(model_to_dict(obj))
# print(data)
# return HttpResponse(data) # 序列化方式2:
# from django.core import serializers as dcs # 跟from rest_framework import serializers名字冲突了
# data=dcs.serialize("json",book_list)
# return HttpResponse(data) # 序列化方式3:
bs=BookSerializers(book_list,many=True)
return Response(bs.data) views.py
views.py --get请求
方式1:
方式2:
方式3:
示例2 post请求
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# depth = 1 class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
# 序列化方式1:
# from django.forms.models import model_to_dict
# data=[]
# for obj in book_list:
# data.append(model_to_dict(obj))
# print(data)
# return HttpResponse(data) # 序列化方式2:
# from django.core import serializers as dcs # 跟from rest_framework import serializers名字冲突了
# data=dcs.serialize("json",book_list)
# return HttpResponse(data) # 序列化方式3:
bs=BookSerializers(book_list,many=True)
return Response(bs.data) def post(self, request, *args, **kwargs): bs = BookSerializers(data=request.data, many=False)
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
veiws.py ——post请求
示例3 单条数据的get 和 put
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# exclude = ['authors',]
# depth=1 # def create(self, validated_data):
# authors = validated_data.pop('authors')
# print(authors)
# obj = Book.objects.create(**validated_data)
# obj.authors.add(*authors)
# return obj class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
# 序列化方式1:
# from django.forms.models import model_to_dict
# data=[]
# for obj in book_list:
# data.append(model_to_dict(obj))
# print(data)
# return HttpResponse(data) # 序列化方式2:
# from django.core import serializers as dcs # 跟from rest_framework import serializers名字冲突了
# data=dcs.serialize("json",book_list)
# return HttpResponse(data) # 序列化方式3:
bs=BookSerializers(book_list,many=True)
return Response(bs.data) def post(self, request, *args, **kwargs): bs = BookSerializers(data=request.data, many=False)
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class BookDetailViewSet(APIView): def get(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj)
return Response(bs.data) def put(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
bs=BookSerializers(book_obj,data=request.data)
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
views.py --单条数据的get和put
示例4 外键_超链接
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
publish = serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk") class Meta:
model = Book
fields = "__all__"
# depth=1 class PublshSerializers(serializers.ModelSerializer):
class Meta:
model = Publish
fields = "__all__"
# depth = 1 class AuthorSerializers(serializers.ModelSerializer): class Meta:
model = Author
fields = "__all__"
# depth = 1 class BookViewSet(APIView): def get(self,request,*args,**kwargs):
book_list=Book.objects.all()
# 序列化方式1:
# from django.forms.models import model_to_dict
# data=[]
# for obj in book_list:
# data.append(model_to_dict(obj))
# print(data)
# return HttpResponse(data) # 序列化方式2:
# from django.core import serializers as dcs # 跟from rest_framework import serializers名字冲突了
# data=dcs.serialize("json",book_list)
# return HttpResponse(data) # 序列化方式3:
# bs=BookSerializers(book_list,many=True)
bs=BookSerializers(book_list,many=True,context={"request":request})
return Response(bs.data) def post(self, request, *args, **kwargs): # bs = BookSerializers(data=request.data, many=False)
bs = BookSerializers(data=request.data, many=False,context={"request":request})
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class BookDetailViewSet(APIView): def get(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
# bs=BookSerializers(book_obj)
bs=BookSerializers(book_obj,context={"request":request})
return Response(bs.data) def put(self,request,pk):
book_obj=Book.objects.filter(pk=pk).first()
# bs=BookSerializers(book_obj,data=request.data)
bs=BookSerializers(book_obj,data=request.data,context={"request":request})
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class PublishViewSet(APIView): def get(self,request,*args,**kwargs):
publish_list=Publish.objects.all()
bs=PublshSerializers(publish_list,many=True,context={'request': request})
return Response(bs.data) def post(self,request,*args,**kwargs): bs=PublshSerializers(data=request.data,many=False,context={'request': request})
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class PublishDetailViewSet(APIView): def get(self,request,pk): publish_obj=Publish.objects.filter(pk=pk).first()
bs=PublshSerializers(publish_obj,context={'request': request})
return Response(bs.data) def put(self,request,pk):
publish_obj=Publish.objects.filter(pk=pk).first()
bs=PublshSerializers(publish_obj,data=request.data,context={'request': request})
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class AuthorViewSet(APIView): def get(self,request,*args,**kwargs):
author_list=Author.objects.all()
bs=AuthorSerializers(author_list,many=True,context={'request': request})
return Response(bs.data) def post(self,request,*args,**kwargs): bs=AuthorSerializers(data=request.data,many=False,context={'request': request})
if bs.is_valid():
# print(bs.validated_data)
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors) class AuthorDetailViewSet(APIView): def get(self,request,pk): Author_obj=Author.objects.filter(pk=pk).first()
bs=AuthorSerializers(Author_obj,context={'request': request})
return Response(bs.data) def put(self,request,pk):
Author_obj=Author.objects.filter(pk=pk).first()
bs=AuthorSerializers(Author_obj,data=request.data,context={'request': request})
if bs.is_valid():
bs.save()
return Response(bs.data)
else:
return HttpResponse(bs.errors)
views.py --外键 超链接
暂时未找到多对多的超链接
示例5 使用封装
mixin类
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers from rest_framework import mixins
from rest_framework import generics class BookSerializers(serializers.ModelSerializer):
publish = serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk") class Meta:
model = Book
fields = "__all__"
# depth=1 class PublshSerializers(serializers.ModelSerializer):
class Meta:
model = Publish
fields = "__all__"
# depth = 1 class AuthorSerializers(serializers.ModelSerializer): class Meta:
model = Author
fields = "__all__"
# depth = 1 class BookViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView): queryset = Book.objects.all()
serializer_class = BookSerializers 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 BookDetailViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers 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)
views.py --mixin类编写视图
generices包下面的类
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
publish = serializers.HyperlinkedIdentityField(
view_name='publish_detail',
lookup_field="publish_id",
lookup_url_kwarg="pk") class Meta:
model = Book
fields = "__all__"
# depth=1 class PublshSerializers(serializers.ModelSerializer):
class Meta:
model = Publish
fields = "__all__"
# depth = 1 class AuthorSerializers(serializers.ModelSerializer): class Meta:
model = Author
fields = "__all__"
# depth = 1 from rest_framework import mixins
from rest_framework import generics class BookViewSet(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializers class PublishViewSet(generics.ListCreateAPIView):
queryset = Publish.objects.all()
serializer_class = PublshSerializers class PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
queryset = Publish.objects.all()
serializer_class = PublshSerializers class AuthorViewSet(generics.ListCreateAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializers class AuthorDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
queryset = Author.objects.all()
serializer_class = AuthorSerializers
views.py --使用通用的基于类的视图
测试通过,与上类似,略,
继承viewsets包下的ModelViewSet
from .models import *
from rest_framework import serializers class BookSerializers(serializers.ModelSerializer):
class Meta:
model = Book
fields = "__all__"
# depth=1 from rest_framework import viewsets
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializers
views.py --使用ModelViewSet
from django.urls import path,re_path,include
from testrestfulframework import views urlpatterns = [
re_path(r'^books/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name="book_list"),
re_path(r'^books/(?P<pk>\d+)$', views.BookViewSet.as_view({
'get': 'retrieve',
'put': 'update',
'patch': 'partial_update',
'delete': 'destroy'
}),name="book_detail"),
# re_path(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
# re_path(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
]
urls.py