码迷,mamicode.com
首页 > 其他好文 > 详细

02,rest-framework初识

时间:2019-01-03 23:10:26      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:www.   indent   text   api   web api   index   tps   cas   size   

Rest-framework框架的基本组件

快速实例:

序列化类

开发我们的Web API的第一件事是为我们的Web API提供一种将代码片段实例序列化和反序列化为诸如json之类的表示形式的方式。我们可以通过声明与Django forms非常相似的序列化器(serializers)来实现。
简单实用(基于django原生serializers基于CBV)
models.py
<wiz_code_mirror>
 
 
 
28
 
 
 
 
 
1
from django.db import models
2

3

4
class Book(models.Model):
5
    title = models.CharField(max_length=32)
6
    price = models.IntegerField()
7
    pub_date = models.DateField()
8
    publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
9
    authors = models.ManyToManyField("Author")
10

11
    def __str__(self):
12
        return self.title
13

14

15
class Publish(models.Model):
16
    name = models.CharField(max_length=32)
17
    email = models.EmailField()
18

19
    def __str__(self):
20
        return self.name
21

22

23
class Author(models.Model):
24
    name = models.CharField(max_length=32)
25
    age = models.IntegerField()
26

27
    def __str__(self):
28
        return self.name
 
 
方式一:
分发url
<wiz_code_mirror>
 
 
 
3
 
 
 
 
 
1
    ...
2
    path(‘publishes/‘, views.PublishesView.as_view()),
3
    ...
 
 
视图类
<wiz_code_mirror>
 
 
 
41
 
 
 
 
 
1
import json
2
from django.shortcuts import render, HttpResponse
3
from django.views import View
4
from django.forms.models import model_to_dict
5
from .models import *
6

7

8
class PublishesView(View):
9
        # Publish.objects.all().values("name", "email")
10
        # <QuerySet [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘123@qq.com‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘234@qq.com‘}]>
11
        # list(Publish.objects.all().values("name", "email"))
12
        # [{‘name‘: ‘苹果出版社‘, ‘email‘: ‘123@qq.com‘}, {‘name‘: ‘橘子出版社‘, ‘email‘: ‘234@qq.com‘}]
13
    def get(self, request):
14
        # 序列化方式一
15
        # publish_list = list(Publish.objects.all().values("name", "email"))    # 注意这个list()
16
        # return HttpResponse(json.dumps(publish_list))   
17
        
18
        # 序列化方式二
19
        # 使用model_to_dict(obj)
20
        # publish_list = Publish.objects.all()
21
        # temp = []
22
        # for obj in publish_list:                  # 每一个obj就是类对象
23
        """
24
            temp.append({
25
                "name": "obj.name",
26
                "email": "obj.email"
27
            })
28
        """
29
        #   temp.append(model_to_dict(obj))
30
        # return HttpResponse(json.dumps(temp))
31
        
32
        # 序列化方式三
33
        # publish_list = Publish.objects.all()
34
        # from django.core import serializers
35
        # ret = serializers.serialize(‘json‘, publish_list)
36
        # return HttpResponse(ret)
37
        
38
        采用restframework
39
    
40
    def post(self, request):
41
        pass
 
 
 
技术分享图片
 
 使用rest_framework来序列化
<wiz_code_mirror>
 
 
 
20
 
 
 
 
 
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4

5

6
# 为queryset做序列化
7
class PublishSerializers(serializers.Serializer):
8
    """等同于form.Form"""
9
    name = serializers.CharField()
10
    email = serializers.CharField()
11

12

13
class PublishesView(APIView):
14
    def get(self, request):
15
        publish_list = Publish.objects.all()
16
        ps = PublishSerializers(publish_list, many=True)        # 即可接收Queryset 也可接收 model_obj
17
        return Response(ps.data)
18

19
    def post(self, request):
20
        pass
 
 
    得到的结果在页面中不会显示,会在postmen中显示    
技术分享图片
<wiz_code_mirror>
 
 
 
10
 
 
 
 
 
1
[
2
  {
3
    "name": "苹果出版社",
4
    "email": "123@qq.com"
5
  },
6
  {
7
    "name": "橘子出版社",
8
    "email": "234@qq.com"
9
  }
10
]
 
 
 

解析器request类

django的request类和rest-framework的request类的源码解析
依然是上面的代码        用postmen发送一次post请求
<wiz_code_mirror>
 
 
 
10
 
 
 
 
 
1
class PublishesView(View):
2
    def post(self, request):
3
        print("POST", request.POST)
4
        print("BODY", request.body)
5

6
        return HttpResponse("POST")
7

8
>>>POST <QueryDict: {‘a‘: [‘1‘], ‘b‘: [‘2‘]}>
9
[18/Oct/2018 16:19:02] "POST /publishes/ HTTP/1.1" 200 4
10
BODY b‘a=1&b=2‘
 
 
这个过程里面到底发生了什么?
技术分享图片
<wiz_code_mirror>
 
 
 
2
 
 
 
 
 
1
# request 源码的入口
2
from django.core.handlers.wsgi import WSGIRequest
 
 
rest_framework下面的APIview
<wiz_code_mirror>
 
 
 
1
 
 
 
 
 
1
from rest_framework.views import APIView
 
 
技术分享图片
 
技术分享图片
技术分享图片
技术分享图片
 
OK reas_framework request 请求的取值问题
<wiz_code_mirror>
 
 
 
12
 
 
 
 
 
1
from rest_framework.response import Response
2
from rest_framework.views import APIView
3

4

5
class PublishesView(APIView):
6
    def post(self, request):
7
        # 原生的request支持的操作
8
        # print("POST", request.POST)
9
        # print("BODY", request.body)
10
        
11
    return Response("POST")
12
    
 
 
技术分享图片
<wiz_code_mirror>
 
 
 
27
 
 
 
 
 
1
from rest_framework import serializers
2
from rest_framework.response import Response
3
from rest_framework.views import APIView
4

5

6
# 为queryset做序列化
7
class BookSerializers(serializers.Serializer):
8
    """Book表是一个比较复杂的表包含了一对多与多对多"""
9
    title = serializers.CharField()
10
    price = serializers.IntegerField()
11
    pub_date = serializers.DateField()
12
    # 这怎么办?
13
    # publish = models.ForeignKey("Publish", on_delete=models.CASCADE)  # 一对多
14
    # authors = models.ManyToManyField("Author")    # 多对多
15
    publish = serializers.CharField(source="publish.name")  # 一对多、类名小写
16
    # 多对多的话这个sourse不好使,得到的是Queryset
17
    authors = serializers.CharField(source="authors.all")   # 多对多、类名小写.all() 自动执行
18
    
19
    
20
class BookView(APIView):
21
    def get(self, request):
22
        book_list = Book.objects.all()
23
        bs = BookSerializers(book_list, many=True)
24
        return Response(bs.data)
25

26
    def post(self, request):
27
        pass
 
 
技术分享图片
    Postmen中的数据    
<wiz_code_mirror>
 
 
 
23
 
 
 
 
 
1
[
2
  {
3
    "title": "你好,再见",
4
    "price": 99,
5
    "pub_date": null,
6
    "publish": "苹果出版社",
7
    "authors": "<QuerySet [<Author: pontoon>, <Author: toonpon>]>"        # 得到一个QuerySet
8
  },
9
  {
10
    "title": "再见,你好",
11
    "price": 88,
12
    "pub_date": null,
13
    "publish": "橘子出版社",
14
    "authors": "<QuerySet [<Author: pontoon>]>"
15
  },
16
  {
17
    "title": "谁动了我的奶酪?",
18
    "price": 77,
19
    "pub_date": null,
20
    "publish": "苹果出版社",
21
    "authors": "<QuerySet []>"
22
  }
23
]
 
 
 
<wiz_code_mirror>
 
 
 
31
 
 
 
 
 
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
    """Book表是一个比较复杂的表包含了一对多与多对多"""
4
    title = serializers.CharField()
5
    price = serializers.IntegerField()
6
    pub_date = serializers.DateField()
7
    # 这怎么办?
8
    # publish = models.ForeignKey("Publish", on_delete=models.CASCADE)  # 一对多
9
    # authors = models.ManyToManyField("Author")    # 多对多
10
    publish = serializers.CharField(source="publish.name")  # 一对多、类名小写
11
    # 多对多的话这个sourse不好使,得到的是Queryset
12
    # authors = serializers.CharField(source="authors.all")   # 多对多、类名小写.all() 自动执行
13

14
    # 多对多这样来整
15
    authors = serializers.SerializerMethodField()
16

17
    def get_authors(self, obj):
18
        temp = []
19
        for obj in obj.authors.all():
20
            temp.append(obj.name)
21
        return temp
22
    
23
    
24
class BookView(APIView):
25
    def get(self, request):
26
        book_list = Book.objects.all()
27
        bs = BookSerializers(book_list, many=True)
28
        return Response(bs.data)
29

30
    def post(self, request):
31
        pass
 
 
    Postmen    
<wiz_code_mirror>
 
 
 
28
 
 
 
 
 
1
[
2
  {
3
    "title": "你好,再见",
4
    "price": 99,
5
    "pub_date": null,
6
    "publish": "苹果出版社",
7
    "authors": [
8
      "pontoon",
9
      "toonpon"
10
    ]
11
  },
12
  {
13
    "title": "再见,你好",
14
    "price": 88,
15
    "pub_date": null,
16
    "publish": "橘子出版社",
17
    "authors": [
18
      "pontoon"
19
    ]
20
  },
21
  {
22
    "title": "谁动了我的奶酪?",
23
    "price": 77,
24
    "pub_date": null,
25
    "publish": "苹果出版社",
26
    "authors": []
27
  }
28
]
 
 
这样的数据就比较好
ModelSerialezer
技术分享图片
 
POST请求的数据
<wiz_code_mirror>
 
 
 
37
 
 
 
 
 
1
# 为queryset做序列化
2
class BookSerializers(serializers.Serializer):
3
    """Book表是一个比较复杂的表包含了一对多与多对多"""
4
    title = serializers.CharField()
5
    price = serializers.IntegerField()
6
    pub_date = serializers.DateField()
7
    # 这怎么办?
8
    # publish = models.ForeignKey("Publish", on_delete=models.CASCADE)  # 一对多
9
    # authors = models.ManyToManyField("Author")    # 多对多
10
    publish = serializers.CharField(source="publish.pk")  # 一对多、类名小写
11
    # 多对多的话这个sourse不好使,得到的是Queryset
12
    # authors = serializers.CharField(source="authors.all")   # 多对多、类名小写.all() 自动执行
13

14
    # 多对多这样来整
15
    authors = serializers.SerializerMethodField()
16

17
    def get_authors(self, obj):
18
        temp = []
19
        for obj in obj.authors.all():
20
            temp.append(obj)
21
        return temp
22
    
23
    # 这个地方我们对字段进行了一些列的定制
24
    
25
    
26
class BookView(APIView):
27
    def get(self, request):
28
        ...
29

30
    def post(self, request):
31
        bs = BookSerializers(data=request.data)
32
        if bs.is_valid():                    # 验证码提交过来的数据是否合格
33
            print(bs.validated_data)         # 如果是合格的数据走了内置的create()方法,将提交过来的保存至数据库中!
34
            bs.save()                        # 保存
35
            return Response(bs.data)         # 返回数据
36
        else:
37
            return Response(bs.errors)       # 返回错误
 
 
    用postmen传数据过来会报错    
技术分享图片
技术分享图片
 
    该咋整,如何将数据保存至数据库中咧?    
<wiz_code_mirror>
 
 
 
34
 
 
 
 
 
1
class BookSerializers(serializers.ModelSerializer):
2
    """Book表是一个比较复杂的表包含了一对多与多对多"""
3
    class Meta:
4
        model = Book
5
        fields = "__all__"
6
    publish = serializers.CharField(source="publish.pk")  # 一对多、类名小写
7

8
    def create(self, validated_data):
9
       """重写源码中的create方法"""
10
        print("validated_data", validated_data)
11
        book = Book.objects.create(title=validated_data["title"],
12
                                   price=validated_data[‘price‘],
13
                                   publish_id=validated_data[‘publish‘][‘pk‘],
14
                                   )
15
        book.authors.add(*validated_data["authors"])
16
        return book
17
    
18
>>> validated_data {‘publish‘: {‘pk‘: ‘1‘}, ‘title‘: ‘java‘, ‘price‘: 20, ‘authors‘: [<Author: pontoon>, <Author: toonpon>]}
19

20

21

22
class BookView(APIView):
23
    def get(self, request):
24
        book_list = Book.objects.all()
25
        bs = BookSerializers(book_list, many=True)
26
        return Response(bs.data)
27

28
    def post(self, request):
29
        bs = BookSerializers(data=request.data)
30
        if bs.is_valid():
31
            bs.save()
32
            return Response(bs.data)
33
        else:
34
            return Response(bs.errors)
 
 
    Postmen在次提交数据    
技术分享图片
    返回成功啦!    ,不过这也太吉儿的复杂了把,还得花时间整理!透~
 

单条数据的get/post请求

    url    
<wiz_code_mirror>
 
 
 
4
 
 
 
 
 
1
    # 获取所有数据的URL
2
    path(‘books/‘, views.BookView.as_view()),
3
    # 获取单条数据的URL
4
    path(‘books/<int:pk>‘, views.BookDetailView.as_view()),
 
 
    视图    
<wiz_code_mirror>
 
 
 
x
 
 
 
 
 
1
class BookDetailView(APIView):
2
    """获取单条数据"""
3
    def get(self, request, pk):
4
        book = Book.objects.get(pk=pk)
5
        bs = BookModelSerializers(book)
6
        return Response(bs.data)
7

8
    def put(self, request, pk):
9
        """ 想那张表提交那条数据 """
10
        book = Book.objects.get(pk=pk)
11
        bs = BookModelSerializers(book, data=request.data)
12
        if bs.is_valid():
13
            bs.save()
14
            return Response(bs.errors)        
15

16
    def delete(self, request, pk):
17
        Book.objects.get(pk=pk).delete()
18

19
        return Response()
 
 
 
 
技术分享图片
 

序列化超链接字段

技术分享图片
第二步
技术分享图片
 
技术分享图片
 
效果如图
技术分享图片
 


 
 
 
 
 
 
 
 
 
 
 

02,rest-framework初识

标签:www.   indent   text   api   web api   index   tps   cas   size   

原文地址:https://www.cnblogs.com/pontoon/p/10217408.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!