zoukankan      html  css  js  c++  java
  • 02,rest-framework初识

    Rest-framework框架的基本组件

    快速实例:

    序列化类

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

     
     
     
    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

     
     
     
    3
     
     
     
     
     
    1
        ...
    2
        path('publishes/', views.PublishesView.as_view()),
    3
        ...
     
     
     
    视图类

     
     
     
    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
     
     
     
    得到数据
    model_to_dict(obj)
    {'id': 1, 'name': '苹果出版社', ‘email’: '123@qq.com'}
     使用rest_framework来序列化

     
     
     
    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中显示
     
     
     
     
     
     
    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请求

     
     
     
    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'
     
     
     
    这个过程里面到底发生了什么?
     
    这个过程其实就是一次Django的请求周期

     
     
     
    2
     
     
     
     
     
    1
    # request 源码的入口
    2
    from django.core.handlers.wsgi import WSGIRequest
     
     
    rest_framework下面的APIview

     
     
     
    1
     
     
     
     
     
    1
    from rest_framework.views import APIView
     
     
     
     

    OK reas_framework request 请求的取值问题

     
     
     
    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
        
     
     
     

     
     
     
    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中的数据    

     
     
     
    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
    ]
     
     
     
     
     
     
    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    

     
     
     
    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请求的数据

     
     
     
    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传数据过来会报错    

    该咋整,如何将数据保存至数据库中咧?    

     
     
     
    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    

     
     
     
    4
     
     
     
     
     
    1
        # 获取所有数据的URL
    2
        path('books/', views.BookView.as_view()),
    3
        # 获取单条数据的URL
    4
        path('books/<int:pk>', views.BookDetailView.as_view()),
     
     
     
       视图    

     
     
     
    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()
     
     
     
     

    序列化超链接字段

     
    第二步
     
     

     
    效果如图
     
     
     
  • 相关阅读:
    Eclipse快捷键大全,导包快捷键:ctrl+Shift+/【转】
    xml合并工具【原】
    解决win10无线无故断网,重启才恢复正常的情况【原】
    PL/SQL可以连oracle,但是jdbc连不上 【转】
    Java 编程下使用 Class.forName() 加载类【转】
    Http请求中Content-Type讲解以及在Spring MVC中的应用【转】
    activeMQ
    概念,包括对象,接口,类,方法
    javabean
    session
  • 原文地址:https://www.cnblogs.com/pontoon/p/10217408.html
Copyright © 2011-2022 走看看