Django如何实现序列化?

我们知道WEB应用模式分为两种:前后端不分离和前后端分离的模式。所谓前后端不分离就是在前端页面看到的效果都是由后端控制的,由后端页面渲染或者重定向,也就是后端需要控制前端的展示,前端与后端的耦合度很高,这种模式比较适合纯网页应用,但是后端对接APP时,APP可能并不需要后端返回一个HTML网页,而仅仅是数据本身,所以后端原本返回网页的接口不在适用前端APP应用,为了对接APP后端还需再开发一套接口。

而前后端分离之后后端仅返回前端所需要的数据,不再渲染HTML页面,不再控制前端的效果,只要前端用户看到什么效果,从后端请求的数据如何加载到前端中,都由前端自己决定,网页有网页自己的处理方式,APP有APP的处理方式,但无论哪种前端所需要的数据基本相同,后端仅需开发一套逻辑对外提供数据即可,在前后端分离的应用模式中,前端与后端的耦合度相对较低。在前后端分离的应用模式中,我们通常将后端开发的每一视图都成为一个接口或者API,前端通过访问接口来对数据进行增删改查。那么问题来了、我们如何通过Django从后端返回JSON或者API格式的接口呢?

什么是DRF?

要从后端返回JSON或者API格式的接口、就必须讲到序列化。在开始讲解如何通过Django实现序列化之前我们先一起来看看什么是DRF。Django Rest Framework 是一个强大且灵活的工具包,用以构建Web API。 Django REST Framework可以在Django的基础上迅速实现API,并且自身还带有WEB的测试页面,可以方便的测试自己的API。

序列化和反序列化可以复用的好处如下: 增:效验请求数据>执行反序列化过程>保存数据库>将保存的对象序列化并返回; 删:判断要删除的数据是否存在.>执行数据库删除; 改:判断要修改的数据是否存在>效验请求的参数>执行反序列化过程>保存数据库>将保存的对象序列化并返回; 查:查询数据库>将数据序列化并返回; 特点: 1.提供了定义序列化器 Serializer 的方法,可以快速根据 Django ORM 或者其他库自动序列化/反序列化; 2.提供了丰富的类视图\MIXIN扩展类,简化视图的编写; 3.丰富的定制层级:函数视图\类视图\试图结合到自动生成API,满足各种需要; 4.多种身份认证和权限认证方式的支持; 5.内置了限流系统; 6.直观的API web界面; 7.可扩展性 , 插件丰富;

通过 Django json.dumps实现序列化

Django默认有一个序列化的方法 Json.Dumps。具体代码如下:

from django.views.generic.base import View
from goods.models import Goods


class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        for good in goods:
            json_dict = {}
            json_dict["name"] = good.name
            json_dict["shop_price"] = good.shop_price
            json_dict["market_price"] = good.market_price
            json_list.append(json_dict)
        from django.http import HttpResponse
        import json
        return HttpResponse(json.dumps(json_list), content_type="application/json")

    def post(self, request):
        pass

然后我们去URL里面引入上面的View:

from django.contrib import admin
from django.conf.urls import url
from MxOnline.settings import MEDIA_ROOT
from django.views.static import serve

from goods.views import GoodsListView

urlpatterns = [
    url('admin/', admin.site.urls),

    # 配置图片访问路径
    url(r'^media/(?P<path>.*)$', serve, {"document_root": MEDIA_ROOT}),

    # 商品列表页
    url(r'goods/$', GoodsListView.as_view(), name="goods_list")
]

然后我们就可以启动项目去访问http://127.0.0.1:8000/goods这个接口了。可以看到、我们已经通过简单的示例实现了Goods商品的序列化并返回了JSON格式的数据(请自行安装JSONVIEW插件):

虽然我们上面通过Django实现了Goods的序列化、但是这里面还有很多问题没有解决。比如 image、datetime,外键等字段通过json.dumps实现序列化都会报错的;字段比较多的时候、特别麻烦也容易出错;上面的代码写起来和维护起来都比较麻烦。那么,有没有更简便的方法呢?有的,Django给我们提供了一个方法:model_to_dict。model_to_dict 可以将model转换成一个dict、具体代码如下:

from django.views.generic.base import View
from goods.models import Goods


class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        # for good in goods:
        #     json_dict = {}
        #     json_dict["name"] = good.name
        #     json_dict["shop_price"] = good.shop_price
        #     json_dict["market_price"] = good.market_price
        #     json_list.append(json_dict)

        from django.forms.models import model_to_dict
        for good in goods:
            json_dict = model_to_dict(good)
            json_list.append(json_dict)
        from django.http import HttpResponse
        import json
        return HttpResponse(json.dumps(json_list), content_type="application/json")

    def post(self, request):
        pass

这样我们就不用像上面一样把一个个字段单独提取出来、方便很多、代码量也很多少。但是新的问题又出现了:model_to_dict 不能把所有的字段都序列化。这里我们通过PyCharm的单步调试可以看到、model_to_dict 确实把数据都取了出来,但是我们通过点击F9把程序执行完之后就可以看到错误页面了。页面提示我们ImageFieldFile不是一个JSON序列化对象:

其实,Django为我们提供了一个专门进行序列化的方法 from django.core import serializers,示例代码如下:

from django.views.generic.base import View
from goods.models import Goods


class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        # for good in goods:
        #     json_dict = {}
        #     json_dict["name"] = good.name
        #     json_dict["shop_price"] = good.shop_price
        #     json_dict["market_price"] = good.market_price
        #     json_list.append(json_dict)

        from django.forms.models import model_to_dict
        for good in goods:
            json_dict = model_to_dict(good)
            json_list.append(json_dict)

        import json
        from django.core import serializers
        json_data = serializers.serialize("json", goods)
        from django.http import HttpResponse, JsonResponse
        import json
        return HttpResponse(json_data, content_type="application/json")

    def post(self, request):
        pass

我们再次启动项目并访问 http://127.0.0.1:8000/goods 接口,我们可以看到数据已经成功返回。但是还没完、Django还有没有其他的实现序列化的方法呢?有的。

上面我们是通过Django提供的HttpResponse方法完成的HTTP请求,Django除了给我们提供了一个HttpResponse以外,还给我们提供了一个JsonResponse。这里我们为了使代码更加简洁、我们使用JsonResponse来实现序列化:

from django.views.generic.base import View
from goods.models import Goods


class GoodsListView(View):
    def get(self, request):
        json_list = []
        goods = Goods.objects.all()[:10]
        # for good in goods:
        #     json_dict = {}
        #     json_dict["name"] = good.name
        #     json_dict["shop_price"] = good.shop_price
        #     json_dict["market_price"] = good.market_price
        #     json_list.append(json_dict)

        from django.forms.models import model_to_dict
        for good in goods:
            json_dict = model_to_dict(good)
            json_list.append(json_dict)

        import json
        from django.core import serializers
        json_data = serializers.serialize("json", goods)
        json_data = json.loads(json_data)
        from django.http import HttpResponse, JsonResponse
        import json
        # 这里我们必须要设置safe=False这个参数、不然页面会报错的。
        return JsonResponse(json_data, safe=False)

    def post(self, request):
        pass

好了、跟上面一样、我们可以正常拿到数据了。我们现在虽然返回了一个Json、但是这里面还有很多问题没有解决比如输入、检测、序列化的自定义、组合等问题。这些工作就需要我们通过DRF来实现了、那么如何通过DRF实现序列化呢?且听下回分解。

推荐文章

1条评论

  1. Hello. This article was extremely motivating, particularly since I was browsing for thoughts on this issue last Monday. Priscilla Charlton Teri

发表评论

邮箱地址不会被公开。 必填项已用*标注