rest_framework框架的安装与序列化

rest_framework的安装

pip install django  # django的安装,rest_framework是基于django的
pip install djangorestframework  # rest_framework的安装

rest_framework官方网站>>

序列化

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

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
models.py部分

django原生序列化方式

views.py部分:

from django.shortcuts import render, HttpResponse

# Create your views here.
from django.views import View
from app01 import models


class BookView(View):

    def get(self, request):
        import json
        # 序列化方式1:
        book_list = list(models.Book.objects.all().values("title", "price", "pub_date"))
        return HttpResponse(json.dumps(book_list))

        # 序列化方式2: 利用model_to_dict把对象转换成dict形式
        from django.forms import model_to_dict
        book_list = models.Book.objects.all()
        temp = []
        for book_obj in book_list:
            temp.append(model_to_dict(book_obj))
        print(temp)
        return HttpResponse("ok")

        # 序列化方式3:利用django内置的serializers
        from django.core import serializers
        book_list = models.Book.objects.all()
        ret = serializers.serialize("json", book_list)
        return HttpResponse(json.dumps(ret))

 rest_framework组件序列化

Serializer

views.py部分:

from django.shortcuts import render
# Create your views here.
from app01 import models
from rest_framework.views import APIView
from rest_framework import serializers
from rest_framework.response import Response


# 为queryset,model对象做序列化
class BookSerializers(serializers.Serializer):
    title = serializers.CharField(max_length=32)
    price = serializers.IntegerField()
    pub_date = serializers.DateField()
    publish = serializers.CharField(source="publish.name")  # 一对多字段序列化
    # 多对多字段序列化
    authors = serializers.SerializerMethodField()
    #定义函数处理多对多序列化,函数命名必须为:get_多对多字段
    def get_authors(self, obj):
        temp = []
        for author in obj.authors.all():
            temp.append(author.name)
        return temp
'''
序列化BookSerializers(book_list,many=True)过程:
     temp=[]
     for obj in book_list:
         temp.append({
            "title":obj.title,
            "price":obj.price,
            "pub_date":obj.pub_date,
            "publish":obj.publish, # 相当:str(obj.publish),source="publish.name"相当于:obj.publish.name
            #"authors":obj.authors.all,
            "authors": get_authors(obj)
         })

'''


class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        # 如:传入一个queryset时,many=True,如:obj对象时,不需要many
        bs = BookSerializers(book_list, many=True)
        return Response(bs.data)

 ModelSerializer

views.py部分:

from django.shortcuts import render
# Create your views here.
from app01 import models
from rest_framework.views import APIView
from rest_framework import serializers
from rest_framework.response import Response


# 为queryset,model对象做序列化
class BookSerializers(serializers.ModelSerializer): # 继承serializers.ModelSerializer
    class Meta:
        model = models.Book
        fields = "__all__"
    # 对于一对多,多对多时,序列化的结果值是id值,所以需要另配置,跟serializers.Serializer一样
    publish = serializers.CharField(source="publish.name")  # 一对多字段序列化
    # 多对多字段序列化
    authors = serializers.SerializerMethodField()
    #定义函数处理多对多序列化,函数命名必须为:get_多对多字段
    def get_authors(self, obj):
        temp = []
        for author in obj.authors.all():
            temp.append(author.name)
        return temp


class BookView(APIView):

    def get(self, request):
        book_list = models.Book.objects.all()
        # 如:传入一个queryset时,many=True,如:obj对象时,不需要many
        bs = BookSerializers(book_list, many=True)
        return Response(bs.data)

 提交post请求

class BookView(APIView):

    def post(self, request):
        # post请求的数据
        bs = BookSerializers(data=request.data)  #用户提交的数据request.data
        if bs.is_valid():  # 数据是否合法
            bs.save()  # 相当执行ModelSerializer下的create方法
            return Response(bs.data)  # 返回保存的数据
        else:
            return Response(bs.errors)  # 返回错误信息

如果ModelSerializer自定义了一对多,多对多字段,save()存储报错,需要重写save中的create方法

重写save中的create方法

class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = "__all__"
        # exclude = ['authors',]
        # depth=1

    def create(self, validated_data):
        # 所以合法数据存储的validated_data里
        authors = validated_data.pop('authors')
        # 相当Book.objects.create(title=validated_data["title"],price=validated_data["price"],pub_date=validated_data["pub_date"]
        obj = models.Book.objects.create(**validated_data)  # 打散
        obj.authors.add(*authors)
        return obj

单条数据的get和put请求

class BookDetailViewSet(APIView):

    def get(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj)
        return Response(bs.data)

    def put(self,request,pk):
        book_obj=models.Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,data=request.data)  # 添加一条内容
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

urls部分:

urlpatterns = [
    url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
]

超链接API:Hyperlinked

一对多字段序列化数据显示超链接:

[
    {
        "id": 1,
        "publish": "http://127.0.0.1:8000/publishers/1",
        "title": "三体",
        "price": 233,
        "pub_date": null,
        "authors": [
            1,
            2
        ]
    }
]

views部分:

class BookSerializers(serializers.ModelSerializer):
      publish= serializers.HyperlinkedIdentityField(
                     view_name='publish_detail',  # url反向解析名字
                     lookup_field="publish_id",  # 关联id字段
                     lookup_url_kwarg="pk")  # url分组名称

      class Meta:
          model=models.Book
          fields="__all__"

urls部分:

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailViewSet.as_view(),name="book_detail"),
    url(r'^publishers/$', views.PublishViewSet.as_view(),name="publish_list"),
    url(r'^publishers/(?P<pk>\d+)$', views.PublishDetailViewSet.as_view(),name="publish_detail"),
]

视图三部曲

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import *
from django.shortcuts import HttpResponse
from django.core import serializers


from rest_framework import serializers


class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          #depth=1


class PublshSerializers(serializers.ModelSerializer):

      class Meta:
          model=Publish
          fields="__all__"
          depth=1


class BookViewSet(APIView):

    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        bs=BookSerializers(book_list,many=True,context={'request': request})
        return Response(bs.data)


    def post(self,request,*args,**kwargs):
        print(request.data)
        bs=BookSerializers(data=request.data,many=False)
        if bs.is_valid():
            print(bs.validated_data)
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)


class BookDetailViewSet(APIView):

    def get(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,context={'request': request})
        return Response(bs.data)

    def put(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,data=request.data,context={'request': request})
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)


class PublishViewSet(APIView):

    def get(self,request,*args,**kwargs):
        publish_list=Publish.objects.all()
        bs=PublshSerializers(publish_list,many=True,context={'request': request})
        return Response(bs.data)


    def post(self,request,*args,**kwargs):

        bs=PublshSerializers(data=request.data,many=False)
        if bs.is_valid():
            # print(bs.validated_data)
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)


class PublishDetailViewSet(APIView):

    def get(self,request,pk):

        publish_obj=Publish.objects.filter(pk=pk).first()
        bs=PublshSerializers(publish_obj,context={'request': request})
        return Response(bs.data)

    def put(self,request,pk):
        publish_obj=Publish.objects.filter(pk=pk).first()
        bs=PublshSerializers(publish_obj,data=request.data,context={'request': request})
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)
视图部分

每添加一表新表,复制一套代码,这样就出现很多重复代码。

mixin类编写视图

通过继承mixin类,mixins.ListModelMixin(查看所有数据),mixins.CreateModelMixin(添加数据),mixins.RetrieveModelMixin(查看单条数据),mixins.UpdateModelMixin(更新单条数据),mixins.DestroyModelMixin(删除数据),generics.GenericAPIView(最后必须继承的类),重写视图来减少代码。

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):

    queryset = Book.objects.all()
    serializer_class = BookSerializers

    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 BookDetailViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

    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)

使用通用的基于类的视图

通过使用mixin类,我们使用更少的代码重写了这些视图,但我们还可以再进一步。REST框架提供了一组已经混合好(mixed-in)的通用视图,我们可以使用它来简化我们的views.py模块。

from rest_framework import mixins
from rest_framework import generics

class BookViewSet(generics.ListCreateAPIView):

    queryset = Book.objects.all()
    serializer_class = BookSerializers

class BookDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializers

class PublishViewSet(generics.ListCreateAPIView):

    queryset = Publish.objects.all()
    serializer_class = PublshSerializers

class PublishDetailViewSet(generics.RetrieveUpdateDestroyAPIView):
    queryset = Publish.objects.all()
    serializer_class = PublshSerializers

最终版:viewsets.ModelViewSet

urls.py:

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"),

views.py:


from rest_framework import viewsets
class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializers
posted @ 2019-07-28 20:14  he。  阅读(312)  评论(0编辑  收藏  举报