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

 

posted @ 2019-02-08 21:24  小清是胖子  阅读(397)  评论(0编辑  收藏  举报