DRF之序列化

目录

  • 准备事项
  • 序列化组件初见
  • 序列化字段
  • ModelSerializer
  • 重载create方法
  • 单条数据处理
  • 现阶段代码

准备事项

# 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": "[email protected]"
            }
        ]
        '''

重载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()  # 返回空

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

时间: 2024-08-30 15:28:29

DRF之序列化的相关文章

drf框架 - 序列化组件 | Serializer

序列化组件 知识点:Serializer(偏底层).ModelSerializer(重点).ListModelSerializer(辅助群改) 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 反序列化: 将字符串反序列化成对象用于使用 drf的序列化与反序列化 序列化: 将Model类对象序列化成字符串用户传输 反序列化: 将字符串反序列化成Model对象用于使用 Serializer 序列化准备: 模型层: models.py class User(models.Model): SE

drf框架 - 序列化组件

drf框架 - 序列化组件 序列化与反序列化 序列化: 将对象序列化成字符串用户传输 反序列化: 将字符串反序列化成对象用于使用 drf的序列化与反序列化 序列化: 将Model类对象序列化成字符串用户传输 反序列化: 将字符串反序列化成Model对象用于使用 Serializer 序列化准备: 模型层: models.py class User(models.Model): SEX_CHOICES = [ [0, '男'], [1, '女'], ] name = models.CharFiel

drf框架序列化

目录 drf框架序列化 |反序列化: 序列化与反序列化: drf序列化与反序列化: 序列化: models.py Serializers.py Serializer 反序列化: views.py: ModelSerializers 指定表模型: 自定义反序列化方法: drf框架序列化 |反序列化: 序列化与反序列化: 序列化:对象转换为字符串用于传输 反序列化:字符串转换为对象用于使用 序列化是为了保持对象在内存中的状态,并且可以把保存的对象状态再读出来 a.数据持久化:比如一个电商平台,有数万

DRF如何序列化外键的字段

我觉得在有些应用场景下,这个操作是有用的,因为可以减少一个AJAX的请求,以增加性能. 当然,是二次请求,还是一次传输.这即要考虑用户体验,还要兼顾服务器性能. 一切是有条件的平衡吧.就算是一次传输,字段少的可以全部传,而字段多的就要自定义啦. 在以下样例里,发布单是主表,但相关的项目,组件,用户,如果默认情况下,只显示ID,很不友好. 我们可以将相关的外键名称也一并序列化啦. 重点的DRF: class UserSerializer(serializers.ModelSerializer):

DRF的序列化

DRF视图 APIview django中写CBV的时候是继承View,而rest_framework继承的是APIView,那么他们两个有什么不同 urlpatterns = [ url(r'^book$', BookView.as_view()), url(r'^book/(?P<id>\d+)$', BookEditView.as_view()), ] 不管是View还是APIView最开始调用的都是as_view()方法,看源码有什么区别 我们能看到,APIView继承了View, 并

drf的序列化器

三流 import sys #标准输出流 sys.stdout.write('123\n') sys.stdout.write('456\n') #标准输入流 res=sys.stdin.readline() print(res) #标准错误流:将括号内数据作为错误输出 sys.srderr.write('abc\n') sys.stderr.write('xyz\n) 注意:每个流之间为异步提交,流内为同步提交. JSON文件格式 JSON 值可以是: 数字(整数或浮点数) 字符串(在双引号中

drf 核心 序列化组件Serializer

知识点: Serializer(偏底层).ModelSerialize(重点).ListModelSerializer(辅助群改) 一.Serializer 1.序列化准备: 模型层:models.py class User(models.Model): SEX_CHOICES = [ [0, '男'], [1, '女'], ] name = models.CharField(max_length=64) pwd = models.CharField(max_length=32) phone =

DRF解析组件以及序列化组件

一.知识点回顾: 1.三元运算: 三元运算能够简化我们的代码,请看如下代码: # 定义两个变量 a = 1 b = 2 # 判断a的真假值,如果为True,则将判断表达式的前面的值赋给c,否则将判断表达式后面的值赋给c c = a if a else b print(c) # 1 # 因为a的真假值判断为True,所以c为1 # 定义两个变量 a = 0 b = 2 # 判断a的真假值,如果为True,则将判断表达式的前面的值赋给c,否则将判断表达式后面的值赋给c c = a if a else

drf序列化器serializers.SerializerMethodField()的用法

为什么DRF中有时候返回的json中图片是带域名的,有时候是不带域名的呢? 解析: 带域名的结果是在view中对模型类序列化的,DRF在序列化图片的时候 会检查上下文有没有request,如果有,就给图片加上域名, 比如说我们视图用的是apiview(): 我们需要序列化数据的时候,加  context={"request":request} TestSerilaizer(instance=instance, context={"request":request})