我们写好后端的代码,要把数据交给前端的展示的,这个数据以什么类型给前端呢?学到这里,我们已经知道这个数据最好是json字符串才行,因为网络间的传输,只认字符串或者二进制,字符串就是我们的数据,二进制就是流媒体,比如图片,视频,音频之类的

 

但是我们在后端经过逻辑处理得到的数据并不一定一开始就是个json字符串,所以就需要序列化下

 

补充:

  序列化:将其他类型的数据转为字符串

  反序列化:将字符串转回之前的数据类型(通常是字典类型)

  在Python中,可用于序列化与反序列化的就是json和pickle模块,但是为了与restful规范相映,我们就用json模块(因为前后端分离后,不能保证以后会做成更多的样子,所以选用通用的json字符串)

 

 

创建一个django实例:

 我使用的是django2版本

前后端分离djangorestframework——序列化与反序列化数据

 

建数据库表:

from django.db import models

# 使用这个可以提前声明表名,在使用外键约束时可以不用考虑表前后顺序
__all__ = ['Book', 'Publisher', 'Author']


# Create your models here.

class Book(models.Model):
    title = models.CharField(max_length=32, verbose_name='图书名称')
    CHOICES = ((1, 'python'), (2, 'GO'), (3, 'linux'))
    category = models.IntegerField(choices=CHOICES, verbose_name='图书类别')
    pub_time = models.DateField(verbose_name='出版时间')
    publisher = models.ForeignKey(to='Publisher', on_delete=None)
    author = models.ManyToManyField(to='Author')

    def __str__(self):
        return self.title

    class Meta:
        # 自定义数据库表名
        verbose_name_plural = 'book'
        db_table = verbose_name_plural


class Publisher(models.Model):
    title = models.CharField(max_length=32, verbose_name='出版社名称')

    def __str__(self):
        return self.title

    class Meta:
        verbose_name_plural = 'publish'
        db_table = verbose_name_plural


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name='作者名称')

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'author'
        db_table = verbose_name_plural

  

迁移数据库后,添加数据:

出版社:

前后端分离djangorestframework——序列化与反序列化数据

 

作者表:

前后端分离djangorestframework——序列化与反序列化数据

 

图书表:

前后端分离djangorestframework——序列化与反序列化数据

 

 为app  demo1做路由分发,demo1下创建urls文件,基于CBV式(class-base-view,基于类的视图)的指定url,当然你也可以使用FBV,基于函数的视图函数,不过我建议你使用CBV的,后面你就会体会到了


前后端分离djangorestframework——序列化与反序列化数据

 

定义视图类对象:

前后端分离djangorestframework——序列化与反序列化数据

 

 这里注意使用json的dumps时使用ensure_ascii为false,这样在dump序列化时才不会只转为ascii式的数据,导致一些字段不能被ascii表示

 

启动django,访问/list/:

前后端分离djangorestframework——序列化与反序列化数据

这样没问题了对吧?

但是如果我取得字段有时间呢?我加一个pub_time字段:

class BookView(View):
    def get(self, request):
        book_list = models.Book.objects.values('id', 'title','pub_time')
        book_list = list(book_list)
        ret = json.dumps(book_list, ensure_ascii=False)
        return HttpResponse(ret)

  

再来访问,报错了

前后端分离djangorestframework——序列化与反序列化数据

 

好的,这里就要用到 Jsonresponse

 

Jsonresponse

还是上面的代码,用Jsonresponse返回:

 

前后端分离djangorestframework——序列化与反序列化数据

 

里面加safe参数是因为我们从数据库里取出来的是QuerySet类型,需要转换成list更方便后面的处理。所以传入safe,为什么传入是因为它自己提示的如果是list则传入safe

 

但是,由于我使用的pycharm,最开始是默认使用的django里带的sqlite3,因为时间显示会默认变成时间戳,在取出数据时会提示:Python int too large to convert to C long,意思就是int类型太长了,也就是说不能被识别为时间类型,所以我做了微调,把数据库改成了mysql,添加的数据有点点不一样,但是不影响

 

同样的代码,现在再访问,可以了,但是还是有ascii码的问题:

前后端分离djangorestframework——序列化与反序列化数据

 

通过Jsonresponse的源码可得,需要再传入一个参数就行:

# coding:utf-8
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from django.views import View
import json
# Create your views here.
from demo1 import models


class BookView(View):
    def get(self, request):
        book_list = models.Book.objects.values("id", "title", 'pub_time')
        book_list = list(book_list)
        # ret = json.dumps(book_list, ensure_ascii=False)
        # print(book_list)
        return JsonResponse(book_list, safe=False, json_dumps_params={'ensure_ascii': False})

  

前后端分离djangorestframework——序列化与反序列化数据

如果你打开还是乱码的,你可以考虑换成谷歌浏览器


但是,又来了问题,如果要取出版社publisher字段呢? 图书表中我们只是关联了出版社,此时它就是一个id啊,如果我们要出版社的名字,所以需要再处理:

class BookView(View):
    def get(self, request):
        book_list = models.Book.objects.values("id", "title", 'pub_time','publisher')
        book_list = list(book_list)
        ret = []
        for field in book_list:
            pub_id = field['publisher']
            publish_obj = models.Publisher.objects.filter(id=pub_id).first()
            field['publisher'] = {
                'id':pub_id,
                'title':publish_obj.title
            }
            ret.append(field)

        return JsonResponse(ret, safe=False, json_dumps_params={'ensure_ascii': False})

  

前后端分离djangorestframework——序列化与反序列化数据

 

 

数据是取出来了,但是你应该发现了一个问题,这个太不好维护了,在以后的开发中,肯定是数据很多,外键关联也多,这样一有一个外键关联我们就要重新取处理一次,很麻烦对吧?而且还有choices字段,这个也要处理一下,反正以后遇到任何显示不太符合习惯的都要做下处理,这样是很费时间的,所以聪明的人想到了可以封装一个类或者函数来处理,不过呢,有现成的,django已经给我们封好了一个serializers

 

django-serializers

 

代码作适当处理:

# coding:utf-8
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from django.views import View
import json
# Create your views here.
from demo1 import models
from django.core import serializers

class BookView(View):
    def get(self,request):
        book_list = models.Book.objects.all()
        ret = serializers.serialize('json',book_list,ensure_ascii=False)
        return HttpResponse(ret)

 

访问,很直接的就出来了:

前后端分离djangorestframework——序列化与反序列化数据

但是还是有点小问题,比如category字段无法显示等的,所以这个serializer相对JSONResponse只是好一点点,还是要再处理,则用DRF

 

DRF序列化(get)

 使用DRF那前提必须得装djagnorestframework

前后端分离djangorestframework——序列化与反序列化数据

 

下载完了之后,在django的配置文件settings.py里的app添加此app:
前后端分离djangorestframework——序列化与反序列化数据

 

 接下来就可以使用rest_framework里的工具模块了

 

新建一个py文件,名字随意,这里我在demo1的app根目录下新建一个serializers,定义如下的类,对应models表的字段

前后端分离djangorestframework——序列化与反序列化数据

 

代码:

from rest_framework import serializers


class PublishSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)


class AuthorSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField(max_length=32)


class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    title = serializers.CharField(max_length=32)
    CHOICES = ((1, 'python'), (2, 'GO'), (3, 'linux'))
    category = serializers.ChoiceField(choices=CHOICES,source='get_category_display')
    pub_time = serializers.DateField()

    publisher = PublishSerializer()
    author = AuthorSerializer(many=True)
DRF序列化

相关文章: