django之rest-framework
django的rest-framework是django很贴心的为我们准备的一个实例化app
https://www.django-rest-framework.org/
安装这个app
pip install djangorestframework
安装好之后需要我们在项目的setting里面注册这个app
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', "rest_framework", ]
现在我们就可以使用他的功能了,在使用之前我们可以先来看下我们之前是怎么来序列化的,先导入一些测试的数据:
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish") 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
首先我们看下我们可以使用的第一种方式:
1 from django.views import View 2 from app01.models import * 3 import json 4 5 6 class PublishView(View): 7 8 def get(self,request): 9 # 方式一 10 # publish_list = list(Publish.objects.all().values("id","name")) 11 # 或者也可以这样 12 publish_list = Publish.objects.all() 13 tem = [] 14 for obj in publish_list: 15 tem.append({ 16 "id":obj.pk, 17 "name":obj.name 18 }) 19 20 21 22 # return HttpResponse(json.dumps(publish_list)) 23 return HttpResponse(json.dumps(tem))
结果如下:
[{"id": 1, "name": "\u82f9\u679c\u51fa\u7248\u793e"}, {"id": 2, "name": "\u9999\u8549\u51fa\u7248\u793e"}, {"id": 3, "name": "\u6a58\u5b50\u51fa\u7248\u793e"}]
我们也可以使用下边这种方式:
def get(self,request): from django.forms.models import model_to_dict tem = [] for obj in publish_list: tem.append(model_to_dict(obj)) return HttpResponse(json.dumps(tem))
结果:
[{"id": 1, "name": "\u82f9\u679c\u51fa\u7248\u793e", "email": "123@qq.com"}, {"id": 2, "name": "\u9999\u8549\u51fa\u7248\u793e", "email": "123@qq.com"}, {"id": 3, "name": "\u6a58\u5b50\u51fa\u7248\u793e", "email": "123@qq.com"}]
现在我们来看下带三种 :
1 class PublishView(View): 2 3 def get(self,request): 4 5 6 7 from django.core import serializers 8 ret = serializers.serialize("json",publish_list) 9 10 return HttpResponse(ret)
结果:
[{"model": "app01.publish", "pk": 1, "fields": {"name": "\u82f9\u679c\u51fa\u7248\u793e", "email": "123@qq.com"}}, {"model": "app01.publish", "pk": 2, "fields": {"name": "\u9999\u8549\u51fa\u7248\u793e", "email": "123@qq.com"}}, {"model": "app01.publish", "pk": 3, "fields": {"name": "\u6a58\u5b50\u51fa\u7248\u793e", "email": "123@qq.com"}}]
我们可以看到第三种是最简单的同时也是结果最多的,接下来是我们的rest-framework,在使用之前我们需要先创建一个类,把我们需要序列化的字段放在我们这个类里边.
from rest_framework import serializers
from rest_framework.views import APIView
from rest_framework.response import Response
class BookSerializers(serializers.Serializer):
title = serializers.CharField()
price = serializers.CharField()
pub_date = serializers.CharField()
publish = serializers.CharField(source="publish.email")
# authors = serializers.CharField(source="authors.all")
authors = serializers.SerializerMethodField()
def get_authors(self,obj):
temp = []
for obj in obj.authors.all():
temp.append(obj.name)
return temp
如果是外键关联的我们需要加一个参数source="" 表示用来显示的字段
如果是多对多关联 我们需要用到SerializerMethodField() 这个字段,并且下边用到一个方法做配置 只可以是固定写法 get_加字段名
现在我们就可以使用了
from rest_framework.response import Response
1 class Bookview(APIView): 2 def get(self,request): 3 book_list = Book.objects.all() 4 bs = BookSerializers(book_list,many=True) 5 return Response(bs.data) 6 def post(self,request): 7 pass
结果:
[
{
"title": "三体",
"price": "255",
"pub_date": null,
"publish": "123@qq.com",
"authors": [
"鲁迅"
]
}
]
这里还是有点麻烦的 , 也和modelfrom一样,人家组件也给我们准备了一个差不多的类:
class BookmodelSerializers(serializers.ModelSerializer): class Meta: model = Book fields = "__all__" publish = serializers.CharField (source="publish.name") authors = serializers.SerializerMethodField () def get_authors(self, obj): temp = [] for obj in obj.authors.all(): temp.append(obj.name) return temp
如上 我们在这个类里也是可以自己配置字段的显示名称的
post
对于post请求,我们我们也可以用很少的代码来实现复杂的需求:
1 class Bookview(APIView): 2 def get(self,request): 3 book_list = Book.objects.all() 4 bs = BookmodelSerializers(book_list,many=True) 5 return Response(bs.data) 6 def post(self,request): 7 bs = BookmodelSerializers(data=request.data) 8 if bs.is_valid(): 9 bs.save() 10 return Response(bs.data) 11 else: 12 return Response(bs.errors)
组件自带了校验的功能 , 如上 我们只需要把校验好的数据直接save提交创建就好了 , 没有通过校验的,我们也可以通过error方法取到,给用户返回
这里需要注意一点就是 , 如果我们有自定义显示的字段 save封装的create方法是没有办法帮我们创建的 这时候就需要我们自己重写一个creat方法了
1 class BookmodelSerializers(serializers.ModelSerializer): 2 class Meta: 3 model = Book 4 fields = "__all__" 5 6 publish = serializers.CharField (source="publish.pk") 7 # authors = serializers.SerializerMethodField () 8 # def get_authors(self, obj): 9 # temp = [] 10 # for obj in obj.authors.all(): 11 # temp.append(obj.name) 12 # return temp 13 14 def create(self, validated_data): 15 16 print("validated_data",validated_data) 17 book=Book.objects.create(title=validated_data["title"],price=validated_data["price"],pub_date=validated_data["pub_date"],publish_id=validated_data["publish"]["pk"]) 18 book.authors.add(*validated_data["authors"]) 19 20 return book
写出来的就是上边这个结果了 这里为了能创建成功 上边的字段做一些改动 , 之前的实在不会搞了.
上边的这些我们处理了多条数据 , 如果有用到单条数据我们需要重新创建一个类
1 # 单条数据 2 3 class BookDetailView(APIView): 4 5 def get(self,request,id): 6 book = Book.objects.filter(pk=id).first() 7 bs = BookmodelSerializers(book) 8 return Response(bs.data) 9 10 def put(self,request,id): 11 book = Book.objects.filter(pk=id).first() 12 bs = BookmodelSerializers(book,data=request.data) 13 if bs.is_valid(): 14 bs.save() 15 return Response(bs.data) 16 else: 17 return Response(bs.errors) 18 19 def delete(self,request,id): 20 Book.objects.filter(pk=id).delete() 21 return Response()
超链接
有时候我们会有需求,在点开book的时候 我们希望能看到publish的连接 现在我们可以做如下的配置
1 给每一个url配置一个name,并且给我们需要展示连接的url正则加一个名字,
这里需要注意一点 我们给 参数 起了名字 我们后续需要用到的形参 也是需要叫这个名字的
1 urlpatterns = [ 2 url(r'^admin/', admin.site.urls), 3 url(r'^publish/$', views.PublishView.as_view(),name="publish"), 4 url(r'^book/$', views.Bookview.as_view(),name="book"), 5 url(r'^book/(\d+)/', views.BookDetailView.as_view(),name="book_detail"), 6 url(r'^publish/(?P<pk>\d+)/', views.PublishDetailView.as_view(),name="publish_detail"), 7 ]
2 在book重新配置他的publish关联字段:
1 class BookmodelSerializers(serializers.ModelSerializer): 2 class Meta: 3 model = Book 4 fields = "__all__" 5 6 publish = serializers.HyperlinkedIdentityField ( 7 view_name='publish_detail', 8 lookup_field="publish_id", 9 lookup_url_kwarg="pk")
上边分别获取了 url的名字 , 正则匹配到的值, 以及(\d+)的名字
然后我们就可以发送get请求看到我们需要的连接了:
这里会有一个报错提示我们加上 context={'request': request} 我们只需要在用到实例化的时候加上就可以可以了,下边的put请求也会收到这个报错,我们就一块加上 class BookDetailView(APIView): def get(self,request,id): book = Book.objects.filter(pk=id).first() bs = BookmodelSerializers(book,context={'request': request}) return Response(bs.data) def put(self,request,id): book = Book.objects.filter(pk=id).first() bs = BookmodelSerializers(book,data=request.data,context={'request': request}) if bs.is_valid(): bs.save() return Response(bs.data) else: return Response(bs.errors) def delete(self,request,id): Book.objects.filter(pk=id).delete() return Response()
现在我们就可以看到这个结果了:
1 { 2 "id": 1, 3 "publish": "http://127.0.0.1:8000/publish/1/", 4 "title": "三体", 5 "price": 255, 6 "pub_date": null, 7 "authors": [ 8 1 9 ] 10 }
一般我们对于增删该查返回值有以下这个规范:
1 这个一般是所有文件的get和post,写到一个类里面 2 /books/ -----get books ----- 返回当前所有数据 3 /books/ -----post books ----- 返回提交数据 4 这个一般是面向单个数据 , 我们写到另外一个类里面 5 /books/(\d+)-----get bookdetail ----- 返回当前查看的单条数据 6 /books/(\d+)-----put bookdetail ----- 返回更新数据 7 /books/(\d+)-----delete bookdetail ----- 返回空
mixin类编写视图
上边我们写好的视图是长成这样子的:
1 from django.shortcuts import render,HttpResponse 2 3 # Create your views here. 4 5 from django.views import View 6 from app01.models import * 7 import json 8 from rest_framework import serializers 9 from rest_framework.views import APIView 10 from rest_framework.response import Response 11 from app01.serializers import * 12 13 14 15 16 17 18 class PublishView(APIView): 19 20 def get(self,request): 21 # 方式一 22 # publish_list = list(Publish.objects.all().values("id","name")) 23 # 或者也可以这样 24 publish_list = Publish.objects.all() 25 # tem = [] 26 # for obj in publish_list: 27 # tem.append({ 28 # "id":obj.pk, 29 # "name":obj.name 30 # }) 31 32 # from django.forms.models import model_to_dict 33 # tem = [] 34 # for obj in publish_list: 35 # tem.append(model_to_dict(obj)) 36 37 from django.core import serializers 38 ret = serializers.serialize("json",publish_list) 39 40 # return HttpResponse(json.dumps(publish_list)) 41 return HttpResponse(ret) 42 43 44 def post(self,request): 45 46 return HttpResponse(666) 47 48 49 50 class Bookview(APIView): 51 def get(self,request): 52 book_list = Book.objects.all() 53 bs = BookmodelSerializers(book_list,many=True,context={'request': request}) 54 return Response(bs.data) 55 def post(self,request): 56 bs = BookmodelSerializers(data=request.data) 57 if bs.is_valid(): 58 bs.save() 59 return Response(bs.data) 60 else: 61 return Response(bs.errors) 62 63 # 单条数据 64 65 class BookDetailView(APIView): 66 67 def get(self,request,id): 68 book = Book.objects.filter(pk=id).first() 69 bs = BookmodelSerializers(book,context={'request': request}) 70 return Response(bs.data) 71 72 def put(self,request,id): 73 book = Book.objects.filter(pk=id).first() 74 bs = BookmodelSerializers(book,data=request.data,context={'request': request}) 75 if bs.is_valid(): 76 bs.save() 77 return Response(bs.data) 78 else: 79 return Response(bs.errors) 80 81 def delete(self,request,id): 82 Book.objects.filter(pk=id).delete() 83 return Response() 84 85 86 87 88 class PublishDetailView(APIView): 89 def get(self, request, pk): 90 publish = Publish.objects.filter (pk=pk).first () 91 ps = PublishSerializers (publish) 92 return Response (ps.data) 93 94 def put(self, request, pk): 95 publish = Publish.objects.filter (pk=pk).first () 96 ps = PublishSerializers (publish, data=request.data) 97 if ps.is_valid (): 98 ps.save () 99 return Response (ps.data) 100 else: 101 return Response (ps.errors) 102 103 def delete(self, request, pk): 104 Publish.objects.filter (pk=pk).delete () 105 return Response ()
我们可以看到有很多重复的代码 , 这时候我们可以用到mixin类 , 很多逻辑帮我们进行了封装:
1 from rest_framework import mixins,generics 2 3 4 5 class AuthorView(mixins.ListModelMixin,mixins.CreateModelMixin,generics.GenericAPIView): 6 queryset = Author.objects.all () 7 serializer_class = AuthorSerializers 8 def get(self, request, *args, **kwargs): 9 return self.list(self, request, *args, **kwargs) 10 def post(self, request, *args, **kwargs): 11 return self.create(self, request, *args, **kwargs)
上边的代码中 , 我们继承了三个类
mixins.ListModelMixin, mixins.CreateModelMixin,
里边帮我们封装了list 和create方法
generics.GenericAPIView 帮我们重写了APIView
queryset = Author.objects.all ()
serializer_class = AuthorSerializers 这两句是固定的写法 , 需要把我们的表名和配置类做一个赋值
我们只需要继承这三个类直接调用就可以了,同样可以看到我们需要的结果
如果是对单个的操作 我们只要继承这几个类就可以了
1 class AuthorDetailView( 2 mixins.UpdateModelMixin, 3 mixins.DestroyModelMixin, 4 mixins.RetrieveModelMixin, 5 generics.GenericAPIView 6 ): 7 queryset = Author.objects.all () 8 serializer_class = AuthorSerializers 9 10 def get(self, request, *args, **kwargs): 11 return self.retrieve(self, request, *args, **kwargs) 12 13 def put(self, request, *args, **kwargs): 14 return self.update(self, request, *args, **kwargs) 15 16 def delete(self, request, *args, **kwargs): 17 return self.destroy(self, request, *args, **kwargs)
这里需要注意一点 我们在填写url的时候参数一定要有一个名字叫pk不然会报错:
1 url(r'^author/(?P<pk>\d+)/', views.AuthorDetailView.as_view(),name="author_detail"),
通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架又为我们做了一层封装 帮我们把上边的几个类封装到了一个类里边 , 我们在使用的时候只需要这样写就可以了:
1 class AuthorView(generics.ListCreateAPIView): 2 queryset = Author.objects.all () 3 serializer_class = AuthorSerializers 4 5 class AuthorDetailView(generics.RetrieveUpdateDestroyAPIView): 6 queryset = Author.objects.all () 7 serializer_class = AuthorSerializers
现在已经很简洁了 REST框架在此基础上又帮我们把两个类合并成了一个类 , 我们只需要把我们的需要用到的方法通过as_view()方法传给我们继承的类就可以了 写法:
1 from rest_framework import viewsets 2 class AuthorView(viewsets.ModelViewSet): 3 queryset = Author.objects.all () 4 serializer_class = AuthorSerializers 5 6 7 8 url: 9 10 url(r'^author/$', views.AuthorView.as_view({ 11 "get":"list", 12 "post":"create" 13 }),name="author"), 14 url(r'^author/(?P<pk>\d+)/', views.AuthorView.as_view({ 15 "get":"retrieve", 16 "put":"update", 17 "delete":"destroy" 18 }),name="author_detail"), 19 ]
认证组件
我们使用认证组件需要配置我们的认证类: 这里我们需要注意 我们的类 里边的方法和返回值是人家提前写好的 这里我们只可以是一个固定的写法
1 from rest_framework import exceptions 2 3 from rest_framework.authentication import BaseAuthentication 4 5 6 from .models import * 7 class TokenAuth(BaseAuthentication): 8 def authenticate(self,request): 9 token = request.GET.get("token") 10 token_obj = Token.objects.filter(token=token).first() 11 if not token_obj: 12 raise exceptions.AuthenticationFailed("验证失败123!") 13 else: 14 return token_obj.user.name,token_obj.token
在我们需要认证的视图当中要有如下写法:
1 from rest_framework import viewsets 2 from app01.utils import TokenAuth 3 class AuthorView(viewsets.ModelViewSet): 4 authentication_classes = [TokenAuth, ] 5 queryset = Author.objects.all () 6 serializer_class = AuthorSerializers
我们也可以配置全局的认证:
1 REST_FRAMEWORK = { 2 "DEFAULT_AUTHENTICATION_CLASSES": ["app01.utils.TokenAuth",] 3 }
权限组件
权限组件这里和认证组件是很像的 写法如下:
1 我们配置一个权限类: 2 3 class Svip_permission(object): 4 def has_permission(self,request,view): 5 username = request.user 6 user_type = User.objects.filter(name=username).first().user_type 7 if user_type == 3: 8 return True 9 else: 10 return False 11 12 和上边一样在我们视图里边添加我们的配置类: 13 permission_classes = [Svip_permission]
这里我们也是可以配置全局的 如果用不到全局 我们只需要在用到的地方加上这个配置类就可以了 也可以在有了全局配置之后我们给
permission_classes 赋值一个空的列表
1 'DEFAULT_PERMISSION_CLASSES': ( 2 'rest_framework.permissions.AllowAny', 3 ), 4 5 6 7 我们把我们写好的类放在这个里边就可以了
频率组件
和上边用了同样的玩法 如下:
1 class VisitRateThrottle(object): 2 def allow_request(self,request,view): 3 pass 4 5 6 7 throttle_classes = [VisitRateThrottle] 8 9 10 11 'DEFAULT_THROTTLE_CLASSES': (),
解析器
REST框架比django多配置了Json的解析器 下边是配置和使用:
1 from rest_framework.parsers import JSONParser 2 3 4 5 class JSONParser(BaseParser): 6 """ 7 Parses JSON-serialized data. 8 """ 9 media_type = 'application/json' 10 renderer_class = renderers.JSONRenderer 11 strict = api_settings.STRICT_JSON 12 13 def parse(self, stream, media_type=None, parser_context=None): 14 """ 15 Parses the incoming bytestream as JSON and returns the resulting data. 16 """ 17 parser_context = parser_context or {} 18 encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) 19 20 try: 21 decoded_stream = codecs.getreader(encoding)(stream) 22 parse_constant = json.strict_constant if self.strict else None 23 return json.load(decoded_stream, parse_constant=parse_constant) 24 except ValueError as exc: 25 raise ParseError('JSON parse error - %s' % six.text_type(exc)) 26 27 28 class FormParser(BaseParser): 29 """ 30 Parser for form data. 31 """ 32 media_type = 'application/x-www-form-urlencoded' 33 34 def parse(self, stream, media_type=None, parser_context=None): 35 """ 36 Parses the incoming bytestream as a URL encoded form, 37 and returns the resulting QueryDict. 38 """ 39 parser_context = parser_context or {} 40 encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) 41 data = QueryDict(stream.read(), encoding=encoding) 42 return data 43 44 45 class MultiPartParser(BaseParser): 46 """ 47 Parser for multipart form data, which may include file data. 48 """ 49 media_type = 'multipart/form-data' 50 51 def parse(self, stream, media_type=None, parser_context=None): 52 """ 53 Parses the incoming bytestream as a multipart encoded form, 54 and returns a DataAndFiles object. 55 56 `.data` will be a `QueryDict` containing all the form parameters. 57 `.files` will be a `QueryDict` containing all the form files. 58 """ 59 parser_context = parser_context or {} 60 request = parser_context['request'] 61 encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) 62 meta = request.META.copy() 63 meta['CONTENT_TYPE'] = media_type 64 upload_handlers = request.upload_handlers 65 66 try: 67 parser = DjangoMultiPartParser(meta, stream, upload_handlers, encoding) 68 data, files = parser.parse() 69 return DataAndFiles(data, files) 70 except MultiPartParserError as exc: 71 raise ParseError('Multipart form parse error - %s' % six.text_type(exc)) 72 73 74 class FileUploadParser(BaseParser): 75 """ 76 Parser for file upload data. 77 """ 78 media_type = '*/*' 79 errors = { 80 'unhandled': 'FileUpload parse error - none of upload handlers can handle the stream', 81 'no_filename': 'Missing filename. Request should include a Content-Disposition header with a filename parameter.', 82 } 83 84 def parse(self, stream, media_type=None, parser_context=None): 85 """ 86 Treats the incoming bytestream as a raw file upload and returns 87 a `DataAndFiles` object. 88 89 `.data` will be None (we expect request body to be a file content). 90 `.files` will be a `QueryDict` containing one 'file' element. 91 """ 92 parser_context = parser_context or {} 93 request = parser_context['request'] 94 encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) 95 meta = request.META 96 upload_handlers = request.upload_handlers 97 filename = self.get_filename(stream, media_type, parser_context) 98 99 if not filename: 100 raise ParseError(self.errors['no_filename']) 101 102 # Note that this code is extracted from Django's handling of 103 # file uploads in MultiPartParser. 104 content_type = meta.get('HTTP_CONTENT_TYPE', 105 meta.get('CONTENT_TYPE', '')) 106 try: 107 content_length = int(meta.get('HTTP_CONTENT_LENGTH', 108 meta.get('CONTENT_LENGTH', 0))) 109 except (ValueError, TypeError): 110 content_length = None 111 112 # See if the handler will want to take care of the parsing. 113 for handler in upload_handlers: 114 result = handler.handle_raw_input(stream, 115 meta, 116 content_length, 117 None, 118 encoding) 119 if result is not None: 120 return DataAndFiles({}, {'file': result[1]}) 121 122 # This is the standard case. 123 possible_sizes = [x.chunk_size for x in upload_handlers if x.chunk_size] 124 chunk_size = min([2 ** 31 - 4] + possible_sizes) 125 chunks = ChunkIter(stream, chunk_size) 126 counters = [0] * len(upload_handlers) 127 128 for index, handler in enumerate(upload_handlers): 129 try: 130 handler.new_file(None, filename, content_type, 131 content_length, encoding) 132 except StopFutureHandlers: 133 upload_handlers = upload_handlers[:index + 1] 134 break 135 136 for chunk in chunks: 137 for index, handler in enumerate(upload_handlers): 138 chunk_length = len(chunk) 139 chunk = handler.receive_data_chunk(chunk, counters[index]) 140 counters[index] += chunk_length 141 if chunk is None: 142 break 143 144 for index, handler in enumerate(upload_handlers): 145 file_obj = handler.file_complete(counters[index]) 146 if file_obj is not None: 147 return DataAndFiles({}, {'file': file_obj}) 148 149 raise ParseError(self.errors['unhandled']) 150 151 def get_filename(self, stream, media_type, parser_context): 152 """ 153 Detects the uploaded file name. First searches a 'filename' url kwarg. 154 Then tries to parse Content-Disposition header. 155 """ 156 try: 157 return parser_context['kwargs']['filename'] 158 except KeyError: 159 pass 160 161 try: 162 meta = parser_context['request'].META 163 disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8')) 164 filename_parm = disposition[1] 165 if 'filename*' in filename_parm: 166 return self.get_encoded_filename(filename_parm) 167 return force_text(filename_parm['filename']) 168 except (AttributeError, KeyError, ValueError): 169 pass 170 171 def get_encoded_filename(self, filename_parm): 172 """ 173 Handle encoded filenames per RFC6266. See also: 174 https://tools.ietf.org/html/rfc2231#section-4 175 """ 176 encoded_filename = force_text(filename_parm['filename*']) 177 try: 178 charset, lang, filename = encoded_filename.split('\'', 2) 179 filename = urlparse.unquote(filename) 180 except (ValueError, LookupError): 181 filename = force_text(filename_parm['filename']) 182 return filename
我们在视图中和全局的使用:
1 parser_classes = [] 2 3 4 5 全局: 6 'DEFAULT_PARSER_CLASSES': ( 7 'rest_framework.parsers.JSONParser', 8 'rest_framework.parsers.FormParser', 9 'rest_framework.parsers.MultiPartParser' 10 ),
url控制
我们的url写法有很多复用 ,可以用如下方法进行封装:
1 from django.urls import include, path 2 from rest_framework import routers 3 from tutorial.quickstart import views 4 5 router = routers.DefaultRouter() 6 router.register(r'users', views.UserViewSet) 7 router.register(r'groups', views.GroupViewSet) 8 9 # Wire up our API using automatic URL routing. 10 # Additionally, we include login URLs for the browsable API. 11 urlpatterns = [ 12 path('', include(router.urls)), 13 path('api-auth/', include('rest_framework.urls', namespace='rest_framework')) 14 ]
分页和偏移分页
1 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination 2 3 class PNPagination(PageNumberPagination): 4 page_size = 1 5 page_query_param = 'page' 6 page_size_query_param = "size" 7 max_page_size = 5 8 9 class BookViewSet(viewsets.ModelViewSet): 10 11 queryset = Book.objects.all() 12 serializer_class = BookSerializers 13 def list(self,request,*args,**kwargs): 14 15 book_list=Book.objects.all() 16 pp=LimitOffsetPagination() 17 pager_books=pp.paginate_queryset(queryset=book_list,request=request,view=self) 18 print(pager_books) 19 bs=BookSerializers(pager_books,many=True) 20 21 #return Response(bs.data) 22 return pp.get_paginated_response(bs.data)
偏移分页
1 from rest_framework.pagination import LimitOffsetPagination
版本组件:
1 1. 添加配置 2 REST_FRAMEWORK = { 3 4 .... 5 6 'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', 7 'ALLOWED_VERSIONS':['v1','v2'], # 允许的版本 8 'VERSION_PARAM':'version', # 参数 9 'DEFAULT_VERSION':'v1', # 默认版本 10 .... 11 } 12 13 2. 设置路由 14 15 s9luffycity/urls.py 16 urlpatterns = [ 17 #url(r'^admin/', admin.site.urls), 18 url(r'^api/(?P<version>\w+)/', include('api.urls')), 19 ] 20 21 api/urls.py 22 urlpatterns = [ 23 url(r'^course/$', course.CourseView.as_view()), 24 ] 25 26 3. 获取版本 27 request.version 获取版本 28
表关联:
1 class CourseDtailRest(serializers.ModelSerializer): 2 class Meta: 3 model = Course_detail 4 fields = "__all__" 5 # 取出关联的表 一般不推荐使用 6 depth = 1