写后台的时候经常需要写数据接口,这时就需要用到序列化工具, 而默认到序列化工具对 Django model 的序列化支持有限。 同时 Django 本身的序列化工具我在使用时也觉得有诸多不便,因此我尝试自己写了一个快速序列化工具,帮助我快速简单的实现数据接口。
Django Simple Serializer 是一个可以帮助开发者快速将 Django 数据或者 python data 序列化为 json|raw 数据的工具。
对于序列化 Django 数据的解决方案已经有以下几种:
Django内建序列化器, 它可以序列化Django model query set 但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 , 这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外, 如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。
和上面一样, 如果你的model里有 DateTimeField 或者其他特殊的 Field 以及额外数据, QuerySet.values() 同样没法工作。
django-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。 他拥有完善的序列化器,但在使用之前你需要花费一些时间入门, 并学习 cbv 的开发方式, 对于有时间需求的项目或者已经存在的项目需要增加数据接口时显然这不是最好的解决方案。
我希望可以快速简单的序列化数据, 所以我设计了一种可以不用任何额外的配置与学习而将Django data 或者 python data 序列化为相应的数据的简单的方式。 这就是为什么我写了 django simple serializer。
Django >= 1.5
Python 2.5 及以上 (暂不支持 python 3)
Install using pip:
pip install django-simple-serializer
假设我们有以下Django models:
class Classification(models.Model):
c_name = models.CharField(max_length=30, unique=True)
class Article(models.Model):
caption = models.CharField(max_length=50)
classification = models.ForeignKey(Classification, related_name=\'cls_art\')
content = models.TextField()
publish = models.BooleanField(default=False)
使用django simple serializer的简单例子:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list)
data:
[{\'read_count\': 0, \'create_time\': 1432392456.0, \'modify_time\': 1432392456.0, \'sub_caption\': u\'first\', \'comment_count\': 0, u\'id\': 31}, {\'read_count\': 0, \'create_time\': 1432392499.0, \'modify_time\': 1432392499.0, \'sub_caption\': u\'second\', \'comment_count\': 0, u\'id\': 32}]
默认情况下, 序列器会返回一个 list 或者 dict(对于单个model实例), 你可以设置参数 “output_type” 来决定序列器返回 json/raw.
提供序列器
function serializer(data, datetime_format=\’timestamp\’, output_type=\’raw\’, include_attr=None, except_attr=None, foreign=False, many=False)
data(_Required_|(QuerySet, Page, list, django model object))-待处理数据
datetime_format(_Optional_|string)-如果包含 datetime 将 datetime 转换成相应格式.默认为 \”timestamp\”(时间戳)
output_type(_Optional_|string)-serialize type. 默认“raw”原始数据,即返回list或dict
include_attr(_Optional_|(list, tuple))-只序列化 include_attr 列表里的字段。默认为 None
exclude_attr(_Optional_|(list, tuple))-不序列化 except_attr 列表里的字段。默认为 None
foreign(_Optional_|bool)-是否序列化 ForeignKeyField 。include_attr 与 exclude_attr 对 ForeignKeyField 依旧有效。 默认为 False
many(_Optional_|bool)-是否序列化 ManyToManyField 。include_attr 与 exclude_attr 对 ManyToManyField 依旧有效 默认为 False
datetime_format:
parameters | intro |
---|---|
string | 转换 datetime 为字符串。如: \”2015-05-10 10:19:22\” |
timestamp | 转换 datetime 为时间戳。如: \”1432124420.0\” |
例子:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list, datetime_format=\'string\', output_type=\'json\')
data:
[
{
\"read_count\": 0,
\"sub_caption\": \"first\",
\"publish\": true,
\"content\": \"first article\",
\"caption\": \"first\",
\"comment_count\": 0,
\"create_time\": \"2015-05-23 22:47:36\",
\"modify_time\": \"2015-05-23 22:47:36\",
\"id\": 31
},
{
\"read_count\": 0,
\"sub_caption\": \"second\",
\"publish\": false,
\"content\": \"second article\",
\"caption\": \"second\",
\"comment_count\": 0,
\"create_time\": \"2015-05-23 22:48:19\",
\"modify_time\": \"2015-05-23 22:48:19\",
\"id\": 32
}
]
output_type
parameters | intro |
---|---|
raw | 将list或dict中的特殊对象序列化后输出为list或dict |
dict | 同 raw |
json | 转换数据为 json |
xml 转换数据为 xml (暂时去除)
例子:
from dss.Serializer import serializer
article_list = Article.objects.all()[0]
data = serializer(article_list, output_type=\'json\')
data:
{
\"read_count\": 0,
\"sub_caption\": \"first\",
\"publish\": true,
\"content\": \"first article\",
\"caption\": \"first\",
\"comment_count\": 0,
\"create_time\": \"2015-05-23 22:47:36\",
\"modify_time\": \"2015-05-23 22:47:36\",
\"id\": 31
}
include_attr
例子:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list, output_type=\'json\', include_attr=(\'content\', \'caption\',))
data:
[
{
\"content\": \"first article\",
\"caption\": \"first\"
},
{
\"content\": \"second article\",
\"caption\": \"second\"
}
]
exclude_attr
例子:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list, output_type=\'json\', except_attr=(\'content\',))
data:
[
{
\"read_count\": 0,
\"sub_caption\": \"first\",
\"publish\": true,
\"caption\": \"first\",
\"comment_count\": 0,
\"create_time\": 1432392456,
\"modify_time\": 1432392456,
\"id\": 31
},
{
\"read_count\": 0,
\"sub_caption\": \"second\",
\"publish\": false,
\"caption\": \"second\",
\"comment_count\": 0,
\"create_time\": 1432392499,
\"modify_time\": 1432392499,
\"id\": 32
}
]
foreign
序列化数据中的 ForeignKeyField 及其子项目
例子:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list, output_type=\'json\', include_attr=(\'classification\', \'caption\', \'create_time\', foreign=True)
data:
[
{
\"caption\": \"first\",
\"create_time\": 1432392456,
\"classification\": {
\"create_time\": 1429708506,
\"c_name\": \"python\",
\"id\": 1,
\"modify_time\": 1429708506
}
},
{
\"caption\": \"second\",
\"create_time\": 1432392499,
\"classification\": {
\"create_time\": 1430045890,
\"c_name\": \"test\",
\"id\": 5,
\"modify_time\": 1430045890
}
}
]
many
序列化 ManyToManyField
example:
from dss.Serializer import serializer
article_list = Article.objects.all()
data = serializer(article_list, output_type=\'json\', include_attr=(\'classification\', \'caption\', \'create_time\', many=True)
测试数据无 ManyToManyField ,数据格式同上
提供序列器 Mixin
class JsonResponseMixin(object)
datetime_type = \'string\' # 输出datetime时间格式。默认为“string”,可选参数相见dss.Serializer.serializer
foreign = False # 是否序列化ForeignField。默认为False
many = False # 是否序列化ManyToManyField。默认为False
include_attr = None # 只序列化include_attr包含的属性。默认为None,接受一个包含属性名称的tuple
exclude_attr = None # 不序列化exclude_attr包含的属性。默认为None,接受一个包含属性名称的tuple
将普通class based view 转换为返回json数据的class based view,适用于DetailView等
例子:
# view.py
from dss.Mixin import JsonResponseMixin
from django.views.generic import DetailView
from model import Article
class TestView(JsonResponseMixin, DetailView):
model = Article
datetime_type = \'string\'
pk_url_kwarg = \'id\'
# urls.py
from view import TestView
urlpatterns = patterns(\'\',
url(r\'^test/(?P(\\d)+)/$\', TestView.as_view()),
)
访问:localhost:8000/test/1/
response:
{
\"article\": {
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"comments\": [],
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"id\": 32,
\"publish\": false
},
\"object\": {
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"comments\": [],
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"id\": 32,
\"publish\": false
},
\"view\": \"\"
}
class MultipleJsonResponseMixin(JsonResponseMixin):
将列表类视图转换为返回json数据的类视图,适用于ListView等
例子:
# view.py
from dss.Mixin import MultipleJsonResponseMixin
from django.views.generic import ListView
from model import Article
class TestView(MultipleJsonResponseMixin, ListView):
model = Article
query_set = Article.objects.all()
paginate_by = 1
datetime_type = \'string\'
# urls.py
from view import TestView
urlpatterns = patterns(\'\',
url(r\'^test/$\', TestView.as_view()),
)
访问:localhost:8000/test/
response:
{
\"paginator\": \"\",
\"article_list\": [
{
\"classification_id\": 1,
\"read_count\": 2,
\"sub_caption\": \"first\",
\"content\": \"first article\",
\"caption\": \"first\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 31
},
{
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"\",
\"content\": \"testseteset\",
\"caption\": \"hehe\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 33
},
{
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 32
}
],
\"object_list\": [
{
\"classification_id\": 1,
\"read_count\": 2,
\"sub_caption\": \"first\",
\"content\": \"first article\",
\"caption\": \"first\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 31
},
{
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"\",
\"content\": \"testseteset\",
\"caption\": \"hehe\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 33
},
{
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"publish\": false,
\"id\": 32
}
],
\"page_obj\": {
\"current\": 1,
\"next\": 2,
\"total\": 3,
\"page_range\": [
{
\"page\": 1
},
{
\"page\": 2
},
{
\"page\": 3
}
],
\"previous\": null
},
\"is_paginated\": true,
\"view\": \"\"
}
class FormJsonResponseMixin(JsonResponseMixin):
将普通class based view 转换为返回json数据的class based view,适用于CreateView、UpdateView、FormView等
例子:
# view.py
from dss.Mixin import FormJsonResponseMixin
from django.views.generic import UpdateView
from model import Article
class TestView(FormJsonResponseMixin, UpdateView):
model = Article
datetime_type = \'string\'
pk_url_kwarg = \'id\'
# urls.py
from view import TestView
urlpatterns = patterns(\'\',
url(r\'^test/(?P(\\d)+)/$\', TestView.as_view()),
)
访问:localhost:8000/test/1/
response:
{
\"article\": {
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"id\": 32,
\"publish\": false
},
\"form\": [
{
\"field\": \"caption\"
},
{
\"field\": \"sub_caption\"
},
{
\"field\": \"read_count\"
},
{
\"field\": \"comment_count\"
},
{
\"field\": \"classification\"
},
{
\"field\": \"content\"
},
{
\"field\": \"publish\"
}
],
\"object\": {
\"classification_id\": 5,
\"read_count\": 0,
\"sub_caption\": \"second\",
\"content\": \"asdfasdfasdf\",
\"caption\": \"second\",
\"comment_count\": 0,
\"id\": 32,
\"publish\": false
},
\"view\": \"\"
}
当我们想在 model 中加入一些额外的数据并也想被序列化时, 现在可以这样做:
def add_extra(article):
comments = Comment.objects.filter(article=article)
setattr(article, \'comments\', comments)
articles = Article.objects.all()
map(add_extra, articles)
result = serializer(articles)
序列化的结果数据中将会包含\”comments\”哦.
额外加入的数据可以是一个普通的数据类型、 另一个 Django model、 字典、 列表甚至 QuerySet
django simple serializer 的实际例子: 个人网站后台数据接口
项目地址: django-simple-serializer
欢迎大家拍砖并提供宝贵意见。