• Django REST framework 初识


    一、官网快速实例

    quickstart

    # 安装 RESTful
    pip install djangorestframework

    二、序列化

    models.py

    from django.db import models
    
    class Author(models.Model):
        name = models.CharField(max_length=32, verbose_name="作者")
        age = models.IntegerField(verbose_name="年龄")
        def __str__(self):
            return self.name
    
    class Publisher(models.Model):
        name = models.CharField(max_length=32, verbose_name="出版社")
        email = models.EmailField(verbose_name="邮箱")
        address = models.CharField(max_length=128, verbose_name="地址")
        def __str__(self):
            return self.name
    
    class Book(models.Model):
        title = models.CharField(max_length=32, verbose_name="书名")
        price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name="价格")
        publish_date = models.DateField(verbose_name="出版日期")
        # 与Publish建立一对多的关系,外键字段一般建立在多的一方
        publisher = models.ForeignKey(to="Publisher", verbose_name="出版社")
        # 与Author表建立多对多的关系,ManyToManyField通常设置在正向查询多的那一边,自动创建第三张表
        authors = models.ManyToManyField(to="Author", verbose_name="作者")
        def __str__(self):
            return self.title
    View Code

    urls.py

    from django.conf.urls import url
    from appxx import views
    
    urlpatterns = [
        url(r"^publishers/$", views.PublisherList.as_view()),
        url(r"^publishers/(d+)$", views.PublisherDetail.as_view()),
        url(r"^books/$", views.BookList.as_view()),
        url(r"^books/(d+)$", views.BookDetail.as_view()),
    ]

    views.py

    铺垫:

    from django.shortcuts import HttpResponse
    from django.views import View
    from appxx import models
    from django.forms.models import model_to_dict
    from django.core import serializers
    
    
    class PublisherList(View):
        def get(self, request):
            """取数据"""
    
            # 方式一:
            publisher_list = models.Publisher.objects.all().values("name", "email", "address")
            return HttpResponse(publisher_list)
    
            # 方式二:
            publisher_list = models.Publisher.objects.all()
            temp = []
            for obj in publisher_list:
                temp.append(model_to_dict(obj))
            return HttpResponse(temp)
    
            # 方式三:
            publisher_list = models.Publisher.objects.all()
            data = serializers.serialize("json", publisher_list)
            return HttpResponse(data)
      
        def get(self, request):
           pass
    View Code

    RESTful 的 Serializer

    Publisher表(没有一对多和多对多字段)

    from appxx import models
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import serializers
    
    
    class PublisherSerializer(serializers.Serializer):
        name = serializers.CharField(max_length=32)
        email = serializers.EmailField()
        address = serializers.CharField(max_length=128)
    
        def create(self, validated_data):
            # 根据提供的验证过的数据创建并返回一个新的"Publisher"实例
            return models.Publisher.objects.create(**validated_data)
    
        def update(self, instance, validated_data):
            # 根据提供的验证过的数据更新并返回一个已经存在的"Publisher"实例
            instance.name = validated_data.get("name", instance.name)
            instance.email = validated_data.get("email", instance.email)
            instance.address = validated_data.get("address", instance.address)
            instance.save()
            return instance
    
    
    class PublisherList(APIView):
        def get(self, request):
            publisher_list = models.Publisher.objects.all()
            s = PublisherSerializer(publisher_list, many=True)
            return Response(s.data)
    
        def post(self, request):
            s = PublisherSerializer(data=request.data)
            if s.is_valid():
                s.save()
                return Response(s.data)
            return Response(s.errors)
    
    
    class PublisherDetail(APIView):
        def get(self, request, pk):
            publisher = models.Publisher.objects.filter(pk=pk).first()
            s = PublisherSerializer(publisher)
            return Response(s.data)
    
        def put(self, request, pk):
            publisher = models.Publisher.objects.filter(pk=pk).first()
            s = PublisherSerializer(publisher, data=request.data)
            if s.is_valid():
                s.save()
                return Response(s.data)
            return Response(s.errors)
    
        def delete(self, request, pk):
            models.Publisher.objects.filter(pk=pk).delete()
            return Response("删除成功")

    RESTful 的 ModelSerializer

    Book表(有一对多和多对多字段)

    备注说明:ModelSerializer继承Serializer;如果一对多字段中有参数source,post提交数据时 --> 则需要重写save中的create方法;除此之外,对于多对多字段,如果使用下面的方法请求(get)数据,将会得到更直观的数据,但这里并没有解决post、put请求操作。

    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"  # fields = ("title", "price", "publish_date", "publisher", "authors")
    
        # 一对多,通过source="本张表一对多字段.关联的表的任一字段",即可获取到对应的数据;如果不写,则获取到的是pk值
        publisher = serializers.CharField(source="publisher.name")
    
        # 多对多,通过source="本张表多对多字段.all",获取到的是 QuerySet 数据;如果不写,则获取到的是pk值
        # authors = serializers.CharField(source="authors.all")
    
        # 多对多,还可以用下面的方法获取到关联的数据
        # authors = serializers.SerializerMethodField()
    
        # def get_authors(self, obj):  # 格式:get_多对多字段名(self, obj)
        #     temp = []
        #     for author in obj.authors.all():
        #         temp.append(author.name)
        #     return temp
    
        # 重写save中的create方法
        def create(self, validated_data):
            obj = models.Book.objects.create(
                title=validated_data["title"],
                price=validated_data["price"],
                publish_date=validated_data["publish_date"],
                publisher_id=validated_data["publisher"]["name"],
            )
            obj.authors.add(*validated_data["authors"])
            return obj
    
    
    class BookList(APIView):
        def get(self, request):  # 获取书籍列表
            book_list = models.Book.objects.all()
            s = BookSerializer(book_list, many=True)
            return Response(s.data)
    
        def post(self, request):  # 新增书籍
            s = BookSerializer(data=request.data)
            if s.is_valid():
                s.save()  # 实际执行的是create()方法
                return Response(s.data)
            return Response(s.errors)
    
    
    class BookDetail(APIView):
        def get(self, request, pk):  # 获取某本书籍
            book = models.Book.objects.filter(pk=pk).first()
            s = BookSerializer(book)
            return Response(s.data)
    
        def put(self, request, pk):  # 修改某本书籍
            book = models.Book.objects.filter(pk=pk).first()
            s = BookSerializer(book, data=request.data)
            if s.is_valid():
                s.save()  # 实际执行的是update()方法
                return Response(s.data)
            return Response(s.errors)
    
        def delete(self, request, pk):  # 删除某本书籍
            models.Book.objects.filter(pk=pk).delete()
            return Response("删除成功")

    超链接API:HyperlinkedModelSerializer(继承ModelSerializer)

    官网内容

    class BookSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
        publisher = serializers.HyperlinkedIdentityField(
            view_name="publisher_detail",
            lookup_field="publisher_id",
            lookup_url_kwarg="pk"
        )
    
    
    class BookList(APIView):
        def get(self, request):
            book_list = models.Book.objects.all()
            s = BookSerializer(book_list, many=True, context={"request": request})
            return Response(s.data)
    
    
    class BookDetail(APIView):
        def get(self, request, pk):
            book = models.Book.objects.filter(pk=pk).first()
            s = BookSerializer(book, context={"request": request})
            return Response(s.data)

    urls.py部分:

    from django.conf.urls import url
    from appxx import views
    
    urlpatterns = [
        url(r"^publishers/$", views.PublisherList.as_view(), name="publisher_list"),
        url(r"^publishers/(?P<pk>d+)/$", views.PublisherDetail.as_view(), name="publisher_detail"),
        url(r"^books/$", views.BookList.as_view(), name="book_list"),
        url(r"^books/(d+)/$", views.BookDetail.as_view(), name="book_detail"),
    ]

    则获取到的数据,相应字段将改为超链接:

    三、使用mixins

    # views.py
    from
    appxx import models from rest_framework import serializers from rest_framework import mixins from rest_framework import generics class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" class BookList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer 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 BookDetail(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer 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)
    # urls.py
    urlpatterns = [ url(r"^books/$", views.BookList.as_view(), name="book_list"), url(r"^books/(?P<pk>d+)/$", views.BookDetail.as_view(), name="book_detail"), ]

    四、使用基于类的通用视图

    # views.py
    from
    appxx import models from rest_framework import serializers from rest_framework import generics class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book fields = "__all__" class BookList(generics.ListCreateAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer class BookDetail(generics.RetrieveUpdateDestroyAPIView): queryset = models.Book.objects.all() serializer_class = BookSerializer
    # urls.py
    urlpatterns = [ url(r"^books/$", views.BookList.as_view(), name="book_list"), url(r"^books/(?P<pk>d+)/$", views.BookDetail.as_view(), name="book_detail"), ]

    五、ViewSet

    使用ViewSet重构:

    from appxx import models
    from rest_framework import serializers
    from rest_framework import viewsets
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
    
    
    class BookViewSet(viewsets.ModelViewSet):
        queryset = models.Book.objects.all()
        serializer_class = BookSerializer

    将ViewSet明确绑定到URL:

    from django.conf.urls import url
    from appxx import views
    
    urlpatterns = [
        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"),
    ]

    将URL整理一下:

    from django.conf.urls import url
    from appxx import views
    
    book_list = views.BookViewSet.as_view({
            "get": "list",
            "post": "create"})
    book_detail = views.BookViewSet.as_view({
            "get": "retrieve",
            "put": "update",
            "patch": "partial_update",
            "delete": "destroy"})
    
    urlpatterns = [
        url(r"^books/$", book_list, name="book_list"),
        url(r"^books/(?P<pk>d+)/$", book_detail, name="book_detail"),
    ]

    六、使用路由器

    from django.conf.urls import url, include
    from appxx import views
    from rest_framework.routers import DefaultRouter
    
    router = DefaultRouter()
    router.register(r"books", views.BookViewSet)
    router.register(r"publishers", views.PublisherViewSet)
    
    urlpatterns = [
        url(r"", include(router.urls)),
    ]
  • 相关阅读:
    【备忘】(可持久化)线段树
    和别人一起搞的模拟赛 (1) 题解
    和别人一起搞的模拟赛 (1) 题面
    【讲课】基础的数论知识
    斐波那契
    luogu P6222
    luogu P4240
    二分图网络流做题记录
    ds 瞎做
    P6943 [ICPC2018 WF]Conquer The World 解题报告
  • 原文地址:https://www.cnblogs.com/believepd/p/10189517.html
Copyright © 2020-2023  润新知