Django REST framework 序列化

创建一个序列化类

使用序列化有四种方式

  • 使用json模块,完全手写
  • 使用django自带的序列化模块 1,# from django.core import serializers   2,# data=serializers.serialize(“json”,book_list)
  • 使用REST framework 带的序列化方法,但是自己写规则  BookSerializers(serializers.Serializer)
  • 使用REST framework 带的序列化方法,不自定义,完全使用模块 BookSerializers(serializers.ModelSerializer)

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

models部分:

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

views部分:

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.Serializer):           
    title=serializers.CharField(max_length=32)
    price=serializers.IntegerField()
    pub_date=serializers.DateField()
    publish=serializers.CharField(source="publish.name")  # 一对多,序列化时如果想要指定字段,需要使用参数source,跨表用.
    #authors=serializers.CharField(source="authors.all")
    authors=serializers.SerializerMethodField()           # 多对多时,自定义字段字段
    def get_authors(self,obj):   # 名字固定写法 get_*
        temp=[]
        for author in obj.authors.all():
            temp.append(author.name)
        return temp

    class Meta:
        model=Book 
        fields=['title','price','pub_date','authors']

    # 钩子函数
    def validate_title(self, value):
        if '草' in value:
            raise ValidationError('不符合社会主义核心价值观')
        return value


class BookViewSet(APIView):
    def get(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        # 序列化方式1 自己手写json:
        # from django.forms.models import model_to_dict
        # import json
        # data=[]
        # for obj in book_list:
        #     data.append(model_to_dict(obj))
        # print(data)
        # return HttpResponse("ok")

        # 序列化方式2,使用django自带的序列化模块:
        # from django.core import serializers
        # data=serializers.serialize("json",book_list)
        # return HttpResponse(data)

        # 序列化方式3,使用REST framework 带的序列化方法,但是自己写规则:
        bs=BookSerializers(book_list,many=True)
        return Response(bs.data)

        # 序列化方式4,使用REST framework 带的序列化方法,不自定义,完全使用模块,如下

ModelSerializer

# ModelSerializer 继承自 Serializer
class BookSerializers(serializers.ModelSerializer):       # 不自定义,完全使用模块
      class Meta:
          model=Book
          fields="__all__"
          depth=1  # 表的深度,即使用一对多,多对多时,跨表的深度
          extra_kwargs = {
            "tag": {
                "error_messages": {
                    "does_not_exist": '"{pk_value}"对应的tag对象不存在。'
                }
            }
        }

在视图中使用序列化类

提交post(添加)请求

def post(self,request,*args,**kwargs):
    bs=BookSerializers(data=request.data,many=False)  # 实例化 ,many=false 是实例一个对象,many=true 是实例化querset
    if bs.is_valid():
        # print(bs.validated_data)
        bs.save()
        return Response(bs.data)
    else:
        return HttpResponse(bs.errors)

单条数据的get(查询一条)和put(更新一条)请求

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

    def put(self,request,pk):
        book_obj=Book.objects.filter(pk=pk).first()
        bs=BookSerializers(book_obj,data=request.data) # 有data参数,调用save是更新操作
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

重写save中的create方法

重写create方法,当你要对某一个字段进行操作的时候,不能用父类的create方法,source不能被解析出来

class BookSerializers(serializers.ModelSerializer):
      class Meta:
          model=Book
          fields="__all__"
          # exclude = ['authors',]
          # depth=1
          
      def create(self, validated_data):
          authors = validated_data.pop('authors')
          obj = Book.objects.create(**validated_data)
          obj.authors.add(*authors)
          return obj

自定义验证

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from .. import models


class PasswordValidator(object):
    def __init__(self, base):
        self.base = str(base)

    def __call__(self, value):
        if value != self.base:
            message = 'This field must be %s.' % self.base
            raise serializers.ValidationError(message)

    def set_context(self, serializer_field):
        # 执行验证之前调用,serializer_fields是当前字段对象
        pass

class ModelUserSerializer(serializers.ModelSerializer):

    user = serializers.CharField(max_length=32)
    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ['user', 'pwd', 'ut']
        depth = 2
        extra_kwargs = {'user': {'min_length': 6},
                        'pwd': {'validators': [PasswordValidator(666), ]}}
        # read_only_fields = ['user']

超链接API:Hyperlinked

class BookSerializers(serializers.ModelSerializer):
      publish= serializers.HyperlinkedIdentityField(
                     view_name='publish_detail', # 反向解析
                     lookup_field="publish_id",  # 这里是取这个id值,当你循环到那个外键的那个id值的值的时候,作为参数传进去
                     lookup_url_kwarg="pk")      # 把还是那个面的id作为参数传进去,就是在url路由里面的有名分组
      class Meta:
          model=Book
          fields="__all__"
          #depth=1

urls部分:

urlpatterns = [
    url(r'^books/$', views.BookViewSet.as_view(),name="book_list"),    # 需要加name参数
    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"),
]
发布了33 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/fenglepeng/article/details/104698901
今日推荐