django 不包括字段 序列化器_笔记------Django序列化

f0c8f608b03cee97cc99167ccdd5ff01.png

写在前面

最近在捣鼓微信小程序,想着用Django做后端,在微信小程序里展示数据。自己在写Django的时候,一般都是直接将QuerySet对象丢给模板,然后去渲染。但是微信小程序中,是不能接受该对象的。这就得自己写一个API返回一个Json数据格式了。

查阅了解

来自 wiki

JSON(JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。 JSON 数据格式与语言无关。即便它源自JavaScript,但当前很多编程语言都支持 JSON 格式数据的生成和解析。JSON 的官方 MIME 类型是 application/json,文件扩展名是 .json

于是问题自然而然的变成了:如何将Django中的对象转化为Json对象返回。好在Django 提供了一个Serializing Django objects ——— 即序列化对象。然后使用HttpResponse()方法,返回 json数据就OK了。

来自 Django文档

Django's serialization framework provides a mechanism for "translating" Django models into other formats. Usually these other formats will be text-based and used for sending Django data over a wire, but it's possible for a serializer to handle any format (text-based or not).

大概意思如下:

Django的序列化框架提供了一种将Django模型“翻译”为其他格式的机制。通常,这些其他格式将基于文本,并用于通过网络发送Django数据,但是序列化程序可以处理任何格式(无论是否基于文本)

序列化数据

在Django中,序列化数据十分简单:

from django.core import serializers
data = serializers.serialize("json", SomeModel.objects.all(),ensure_ascii=False,fields=('desc','title'))
ensure_ascii 参数默认为False。这是因为 RFC 要求使用UTF-8,UTF-16或UTF-32表示JSON,建议使用 UTF-8 作为默认值,以实现最大的互操作性。序列化程序设置 sure_ascii = True,从而转义输出,以便结果字符串仅包含 ASCII 字符。fields 参数指定序列化字段的子集,如果没有则序列化所有数据。

更多请参阅 官方文档

使用 HttpResponse

在视图 views.py 中使用 HttpResponse() 返回即可

return HttpResponse(data,content_type="application/json")

浏览器查看:

c6b3af5a2b19fe0d8f05b8bc02f48c65.png

微信开发者工具中查看:

3a9ce31128f44f91daa965d2f589ee0a.png

取得返回的数据只需要这样得到所需值:

var desc = res.data[0].fields.desc
var title = res.data[0].fields.title

使用 JsonResponse

JsonResponse 对象:

JsonResponse(data,encoder=DjangoJSONEncoder,safe=True,json_dumps_params=None,** kwargs)
默认Content-Type标头设置为application/json
data必须是dict
safe默认为True,若设置为False可以传递任何对象进行序列化。
继承自 HttpResponse
注意: 设置 safe=False 否则会报错: TypeError : In order to allow non-dict objects to be serialized set the safe parameter to False. 当然,你也可以这样写 JsonResponse({'data':data}),传入一个字典类型。
return JsonResponse(data,safe=False)

浏览器中查看:

ca970b16c986d005d5460f5c2e9f639c.png

显然,其结果还算差强人意。但是在微信开发者工具中可以看见:其得到的json数据为String类型。我们更希望的是返回 object 类型,这是因为从 String 类型中取出我们期望的 desctitle要麻烦的多。

6fd86166b7edb9f690d697d3582a2b2c.png

来自 Python 文档 说明


Extensible JSON encoder for Python data structures. Supports the following objects and types by default:

| Python | JSON |

| ----------- | ------ |

| dict | object |

| list, tuple | array |

| str | string |

| int, float | number |

| True | true |

| False | false |

| None | null |


这张表一目了然,我们序列化后的数据 data 为 str 类型(json编码)。这一点很容易就可以验证。所以我们更期望将其转化成 dict。当然,不要寄希望于这样构造 dict:{'data':data},其作用无异于画蛇添足。可以使用 json.loads(data)将其解码。于是上面代码就变成:

return JsonResponse(json.loads(data),safe=False)

假设项目

假设我们已经创建了一个Django项目 /blogdemo,并创建了一个应用 /blog。下面进行一些简单配置确保项目可以正常启动。

  • setting.pyINSTALLED_APPS 中注册应用
INSTALLED_APPS = [
    'blog', # 配置应用
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
  • urls.py 中配置路由
# blogdemo/blogdemo/urls.py 下
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',include('blog.urls')),    # 路由配置
]

# blogdemo/blog/urls.py 下
urlpatterns = [
    path('wxapi/',views.wxapi,name='wxapi'),
]
  • models.py 中创建简单模型
class Post(models.Model):
    auth = models.ForeignKey('Auth', on_delete=models.CASCADE)
    title = models.CharField(verbose_name="标题",max_length=50) 
    # CharField 的 max_length 属性是必须的
    desc = models.CharField(verbose_name="简述",max_length=200,null=True,blank=True)
    def __str__(self):
        return self.title

class Auth(models.Model):
    name = models.CharField(verbose_name='名字',max_length=50)
    about = models.TextField(verbose_name='关于',null=True,blank=False,default="暂无介绍")
    def __str__(self):
        return self.name
  • views.py 中编写视图函数
def wxapi(request):
    posts = Post.objects.all()
    auth = Auth.objects.all()
    all = list(posts) + list(auth)
    # 序列化
    data = serializers.serialize('json', all, ensure_ascii=False)
    return HttpResponse(data,content_type="application/json")

通过上面的配置,基本上就可以启动项目了。点击http://127.0.0.1:8000/blog/wxapi/ 查看

E:Djangofilesblogdemo>python manage.py makemigrations   # 模型迁移
E:Djangofilesblogdemo>python manage.py migrate
E:Djangofilesblogdemo>python manage.py runserver        # 启动项目

当然,现在页面什么数据都没有,因为还没往数据库中添加数据。可以通过Django提供的shell命令窗口使用api方式添加。也可以创建一个管理员账号,通过配置后台,进行添加。这里就不详细讲了。

总结

HttpResponse更适合返回 serializers 对象,JsonResponse 更合适返回自定义的 dict 类型数据。从 JsonResponse 源码中不难发现,其中对传入的 data 做了 json.dumps()处理,而前面使用json.loads处理传入数据,JsonResponse 最后返回的数据其实就和HttpResponse一样了。是的,没有错,这里我做了个傻子操作。无异于画蛇添足(蠢哭.jpg)。都怪我看到到 json,就想到JsonResponse

JsonResponse 部分源代码:

def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
                 json_dumps_params=None, **kwargs):
        if safe and not isinstance(data, dict):
            raise TypeError(
                'In order to allow non-dict objects to be serialized set the '
                'safe parameter to False.'
            )
        if json_dumps_params is None:
            json_dumps_params = {}
        kwargs.setdefault('content_type', 'application/json')
        data = json.dumps(data, cls=encoder, **json_dumps_params)
        super().__init__(content=data, **kwargs)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值