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

DRF之序列化

时间:2018-09-08 11:51:43      阅读:296      评论:0      收藏:0      [点我收藏+]

标签:post   *args   detail   choices   birt   作用   att   pat   get   

目录

准备事项

# models.py
from django.db import models


class Publisher(models.Model):
    title = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __str__(self):
        return self.title



class Author(models.Model):
    name = models.CharField(max_length=32)
    birth_date = models.DateField()
    gender = models.IntegerField(choices=((0,'male'),(1,'female')),default=0)
    email = models.EmailField(max_length=64)

    def __str__(self):
        return self.name


class Book(models.Model):
    title = models.CharField(max_length=32)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    pub_date = models.DateField()
    word_count = models.IntegerField()
    price = models.IntegerField(null=True,blank=True)

    def __str__(self):
        return self.title
# settings.py
INSTALLED_APPS = [
    'app01',
    'rest_framework',
]

序列化组件初见

利用HttpResponse返回json或者文本数据。

from rest_framework.views import APIView
from django.shortcuts import  HttpResponse
from .models import Publisher
import json
from .models import Publisher
from rest_framework import serializers


class PublisherSerializer(serializers.Serializer):
    title = serializers.CharField()
    address = serializers.CharField()


class PubliserView(APIView):
    """获取所有出版社"""
    def get(self,request,*args,**kwargs):
        # 方式1:
        # publishers = Publisher.objects.all().values()  # query set对象不能直接被序列化
        # publishers = list(publishers)
        # return HttpResponse(json.dumps(publishers), content_type='application/json')


        # 方式2:
        from django.forms.models import model_to_dict
        # publishers = Publisher.objects.all()
        # temp = []
        # for obj in publishers:
        #     temp.append(model_to_dict(obj))

        # return HttpResponse(json.dumps(temp), content_type='application/json')


        # 方式3
        # from django.core import serializers  # django的方法,与rest无关
        # publishers = Publisher.objects.all()
        # ret = serializers.serialize('json',publishers)
        # return HttpResponse(ret)  # 内容更多

        
        # 方式4:
        publishers = Publisher.objects.all()
        ser = PublisherSerializer(instance=publishers,many=True)  # 若实例是对象集合,则必须增加many=True
        print(ser.data)
        # [OrderedDict([('title', '长江出版社'), ('address', '武汉市武昌区')]), OrderedDict([('title', '人民出版社')]
        return HttpResponse(ser.data)

序列化字段

类似django form。

# urls.py
from app01.views import PubliserView, BookView
url(r'^books/',BookView.as_view()),


# views.py
class BookView(APIView):
    def get(self, request, *args, **kwargs):
        book_list = Book.objects.all()
        from .my_serializer import BookSerializer
        ser = BookSerializer(instance=book_list, many=True)

        # 1、返回json格式的字符串,对于浏览器相应内容会渲染到drf模板中,若是postman发的请求直接返回原始的数据
        from rest_framework.response import Response
        return Response(ser.data)
        
        # 2、直接返回字符串
        # return HttpResponse(ser.data)



# my_serializer.py

from rest_framework import serializers

class BookSerializer(serializers.Serializer):
    title = serializers.CharField(max_length=32)
    pub_date = serializers.DateField()
    word_count = serializers.IntegerField()

    # 一对多使:用source属性
    publisher = serializers.CharField(source='publisher.address')  # 可以指定关联表的字段
    price = serializers.IntegerField()

    # 针对多对多字段
    # authors = serializers.CharField(source="authors.all")
    authors = serializers.SerializerMethodField()
    def get_authors(self,obj):
        # print(obj)
        authors = list(obj.authors.all().values_list('name'))  # [('蒋勋',), ('易中天',)]
        # authors = list(obj.authors.all().values('name'))  # [{'name': '蒋勋'}, {'name': '易中天'}]
        authors = [item[0] for item in authors if item]
        return authors


# 本质
'''
book_list = BookSerializer(book_list,many=True)
temp = []
for obj in book_list:
    temp.append({
        "title":str(obj.title),
        "price":obj.price,
        "pub_date":str(obj.pub_date),
        "word_count":obj.word_count,
        "publisher":str(obj.publisher),
        
        "authors":str(get_authors(obj)), # 多对多字段
    })
'''

ModelSerializer

类似与django的model-form。
作用:

  1. 将query_set转换成json数据

    def get(self,request):
        publishers = Publisher.objects.all()
        ser = PublisherSerializer(instance=publishers,many=True)  # 若实例是对象集合,则必须增加many=True
        return Response(ser.data)
  2. 将 model对象 转换成json数据

    def get(self, request, pid):
        p_obj = Publisher.objects.filter(pk=int(pid)).first()
        ps = PublisherSerializer(instance=p_obj)
        return Response(ps.data)

3、做数据校验,将json数据>>>成queryset或者model对象>>>记录:

```
def post(self, request):
    bs = BookSerializers(data=request.data)
    # 做校验
    if bs.is_valid(): 
        # 转换成model对象
        bs.save()  # 把数据保存到数据库中(会有反序列化操作),.save()中有 create()方法
        return Response(bs.data)

    else:
        return HttpResponse(bs.errors)  # bs.errors 表示 错误信息
```

语法实例:

from .models import  *

class BookSerializer(serializers.ModelSerializer):
    """
    仅适用于展示字段
    """
    # 重载默认的字段
    publisher = serializers.CharField(source='publisher.address')  # 可以指定关联表的字段
    price = serializers.IntegerField()

    # 针对多对多字段
    authors = serializers.SerializerMethodField()
    def get_authors(self,obj):
        # print(obj)
        authors = list(obj.authors.all().values_list('name'))  # [('蒋勋',), ('易中天',)]
        # authors = list(obj.authors.all().values('name'))  # [{'name': '蒋勋'}, {'name': '易中天'}]
        authors = [item[0] for item in authors if item]
        return authors

    class Meta:
        model = Book
        fields = '__all__'
        # 对于多余多对多和一对多默认使用pk,一般为id
        depth = 1
        '''
        # 增加前
        [{
            "id": 2,
            "title": "蒋勋说唐诗",
            "pub_date": "2012-02-07",
            "word_count": 12,
            "price": 34,
            "publisher": 1,
            "authors": [
                1
            ]
        },
        
        
        # 增加后
        [
        {
            "id": 2,
            "title": "蒋勋说唐诗",
            "pub_date": "2012-02-07",
            "word_count": 12,
            "price": 34,
            "publisher": {
                "id": 1,
                "title": "长江出版社",
                "address": "武汉市武昌区"
            },
             "authors": [
            {
                "id": 1,
                "name": "蒋勋",
                "birth_date": "1956-10-12",
                "gender": 0,
                "email": "jiangxun@foxmail.com"
            }
        ]
        '''

重载create方法

增加对象记录。

from .my_serializer import BookSerializers

class BookView(APIView):
    def post(self, request, *args, **kwargs):
        """保存提交的数据"""
        bs = BookSerializers(data=request.data)
        if bs.is_valid():  # 做校验
            print('validated_data>>>>>>',bs.validated_data)  # 结果为OrderedDict对象
            '''
            OrderedDict([
            ('title', 'who am i'), ('pub_date', datetime.date(2012, 12, 12)), ('word_count', 12), ('price', 29), 
            ('publisher', <Publisher: 长江出版社>), ('authors', [<Author: 蒋勋>, <Author: 易中天>])
            ])
            '''
            bs.save()  # 把数据保存到数据库中(会有反序列化操作) # .save()中有 create()方法
            print('data>>>>>>', bs.data)  # 结果为字典
            '''
            {'id': 21, 'title': 'who am i', 'pub_date': '2012-12-12', 'word_count': 12, 'price': 29, 'publisher': 1, 'authors': [1, 2]}
            '''
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)  # bs.errors 表示 错误信息
            


# 1、使用默认的字段,则无需定制
# 在postman中提交json格式的数据:{"title":"1212312!","pub_date":"2012-12-12","word_count":12,"price":29,"publisher":1,"authors":[1,2]}
class BookSerializers(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"
        

# 2、定制字段后
class BookSerializers(serializers.ModelSerializer):
    publisher = serializers.CharField(source='publisher.pk')

    class Meta:
        model = Book
        fields = "__all__"
        # exclude = ['authors',]
        # depth=1

    # 处理多对多字段时需要重写 save()中的 create()方法
    def create(self, validated_data):
        print('validated_data>>>>>>>',validated_data)
        '''
        {
            'title': '钢铁是怎样炼成的',
            'pub_date': datetime.date(2012, 12, 12),
            'word_count': 12, 'price': 29,
            'publisher': <Publisher: 长江出版社>,
            'authors': [<Author: 蒋勋>, <Author: 易中天>]
        }
        '''
        book_obj = Book.objects.create(
            title=validated_data['title'],
            pub_date=validated_data['pub_date'],
            word_count=validated_data['word_count'],
            publisher_id=validated_data['publisher']['pk'],  # 注意此处字段名称为publisher_id!!!
            price=validated_data['price'],
        )
        print('book_obj',book_obj)

        # authors = validated_data.pop('authors')
        # obj = Book.objects.create(**validated_data)
        book_obj.authors.add(*validated_data['authors'])
        return book_obj

单条数据处理

对特定对象的删、改、查操作。

# urls
url(r'^books/(?P<id>\d+)/$',BookDetailView.as_view()),


# views.py
class BookDetailView(APIView):
    """对特定书籍的查看、修改和删除操作"""
    def get(self, request, id):
        b_obj = Book.objects.filter(pk=int(id)).first()
        bs = BookSerializers(instance=b_obj)
        return Response(bs.data)

    def put(self, request, id):
        """没有对应的对象则更新,有则修改"""
        b_obj = Book.objects.filter(pk=int(id)).first()
        bs = BookSerializers(instance=b_obj,data=request.data)
        if bs.is_valid():  # 数据需要填写完整
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

    def delete(self, request,id):
        """删除指定的对象"""
        b_obj = Book.objects.filter(pk=int(id)).first()
        b_obj.delete()
        return Response()  # 返回空

例:postman进行put操作
技术分享图片


现阶段代码

urls

from django.conf.urls import url
from django.contrib import admin

from app01.views import PubliserView, BookView, BookDetailView,PubliserDetailView

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publishers/$',PubliserView.as_view()),  # 新增/查询所有
    url(r'^publishers/(?P<pid>\d+)/$',PubliserDetailView.as_view()),  # 编辑/新增/删除
    url(r'^books/$',BookView.as_view()),  # 新增/查询所有
    url(r'^books/(?P<id>\d+)/$',BookDetailView.as_view()),  # 编辑/新增/删除
]

serializer

from rest_framework import serializers
from .models import  *


class PublisherSerializer(serializers.ModelSerializer):

    class Meta:
        model = Publisher
        fields = '__all__'
        # depth = 1


class BookSerializers(serializers.ModelSerializer):

    class Meta:
        model = Book
        fields = "__all__"
        # exclude = ['authors',]
        # depth=1

views

有部分重复代码,有待优化!

from rest_framework.views import APIView
from django.shortcuts import  HttpResponse
from .models import Publisher,Book
from rest_framework.response import Response
from .my_serializer import PublisherSerializer
from .my_serializer import BookSerializers



class PubliserView(APIView):
    def get(self,request):
        """查询并返回所有出版社"""
        publishers = Publisher.objects.all()
        ser = PublisherSerializer(instance=publishers,many=True)  # 若实例是对象集合,则必须增加many=True
        return Response(ser.data)

    def post(self,request):
        """新增出版社"""
        bs = PublisherSerializer(data=request.data)
        if bs.is_valid():
            bs.save()
            return Response(bs.data)
        else:
            return Response(bs.errors)


class BookView(APIView):
    def get(self, request):
        """查询所有书籍"""
        book_list = Book.objects.all()
        ser = BookSerializers(instance=book_list, many=True)

        from rest_framework.response import Response
        return Response(ser.data)

    def post(self, request):
        """新增书籍记录"""
        bs = BookSerializers(data=request.data)
        if bs.is_valid():  # 做校验
            bs.save()  # 把数据保存到数据库中(会有反序列化操作) # .save()中有 create()方法
            return Response(bs.data)

        else:
            return HttpResponse(bs.errors)  # bs.errors 表示 错误信息


class PubliserDetailView(APIView):
    """获取所有出版社"""
    def get(self, request, pid):
        """查询并返回某一个的出版社信息"""
        p_obj = Publisher.objects.filter(pk=int(pid)).first()
        ps = PublisherSerializer(instance=p_obj)
        print(ps)
        return Response(ps.data)

    def put(self, request, pid):
        """修改或新增一条出版社信息"""
        p_obj = Publisher.objects.filter(pk=int(pid)).first()
        ps = PublisherSerializer(instance=p_obj, data=request.data)
        print('ps>>>>',ps)
        if ps.is_valid():  # 数据需要填写完整
            ps.save()
            return Response(ps.data)
        else:
            return HttpResponse(ps.errors)

    def delete(self, request,pid):
        """删除某一条出版社记录"""
        Publisher.objects.filter(pk=int(pid)).delete()
        return Response()  # 返回空


class BookDetailView(APIView):
    def get(self, request, id):
        """查询并返回某一本书籍信息"""
        b_obj = Book.objects.filter(pk=int(id)).first()
        bs = BookSerializers(instance=b_obj)
        return Response(bs.data)

    def put(self, request, id):
        """修改或新增一条书籍信息"""
        b_obj = Book.objects.filter(pk=int(id)).first()
        bs = BookSerializers(instance=b_obj,data=request.data)
        if bs.is_valid():  # 数据需要填写完整
            bs.save()
            return Response(bs.data)
        else:
            return HttpResponse(bs.errors)

    def delete(self, request,id):
        """删除某一条书籍记录"""
        b_obj = Book.objects.filter(pk=int(id)).first()
        b_obj.delete()
        return Response()  # 返回空

DRF之序列化

标签:post   *args   detail   choices   birt   作用   att   pat   get   

原文地址:https://www.cnblogs.com/fqh202/p/9608110.html

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