Repository: bluedazzle/django-simple-serializer Branch: master Commit: 1f2ac16cf551 Files: 18 Total size: 60.7 KB Directory structure: gitextract_eyszi_8u/ ├── .gitignore ├── .travis.yml ├── LICENSE ├── english_version.md ├── readme.md ├── requirements.txt └── src/ ├── README.rst ├── __init__.py ├── dss/ │ ├── Mixin.py │ ├── Serializer.py │ ├── TimeFormatFactory.py │ ├── Warning.py │ └── __init__.py ├── setup.py └── test/ ├── __init__.py ├── test_Mixin.py ├── test_Serializer.py └── test_TimeFormatFactory.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.pyc *.pyo *.sqlite3 .idea/ .idea .DS_Store src/django_simple_serializer.egg-info/ src/dist/ src/build/ .coverage fabfile.py ================================================ FILE: .travis.yml ================================================ language: python python: - "2.6" - "2.7" - "3.2" - "3.3" - "3.4" - "3.5" - "3.5-dev" # 3.5 development branch - "nightly" # currently points to 3.6-dev # command to install dependencies install: "pip install -r requirements.txt" # command to run tests script: nosetests ================================================ FILE: LICENSE ================================================ Copyright © RaPoSpectre. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: english_version.md ================================================ # Django Simple Serializer --- Django Simple Serializer is a serializer to help user serialize django data or python list into json\xml\dict data in a simple way. ## Why Django Simple Serializer ? ### django.core.serializers This is a django built-in serializers, it serialzie querset but not a single model object. In addition, if you have DateTimeField into your model, the serializers will not work well(if you'd like using serialized data directly) ### QuerySet.values() As above, QuerySet.values() also not work well if you have DateTimeField into your model. ### django-rest-framework serializers django-rest-framework is a powerful tools to help you build REST API quickly. It has a powerful serializer but you have to use it with create the corresponding model serializer object first. ### django simple serializer For some people, we just want to get serialized data quickly and simply, so i make a simple way to get serialized data without extra opertion, this is why django simple serializer. ## Requirements ### Python 2: Django >= 1.5 Python >= 2.6 ### Python 3: Django >= 1.8 Python >= 3 ## Installation Install using pip: pip install django-simple-serializer ## Working with django simple serializer ### Serializing objects Assuming that we have django models like these: 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) a simple example with using django models above: 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}] By default, the serializer return a list or a dict(for a single object), you can set the parameter “output_type” to decide the serializer return json/xml/list. ## API Guide #### dss.Serializer Provides the serializer *function* serializer(*data, datetime_format='timestamp', output_type='dict', include_attr=None, exclude_attr=None, deep=False*) #### Parameters: * data(_Required_|(QuerySet, Page, list, django model object))-data to be processed * datetime_format(_Optional_|string)-convert datetime into string.default "timestamp" * output_type(_Optional_|string)-serialize type. default "dict" * include_attr(_Optional_|(list, tuple))-only serialize attributes in include_attr list. default None * exclude_attr(_Optional_|(list, tuple))-exclude attributes in exclude_attr list. default None * foreign(_Optional_|bool)-determines if serializer serialize ForeignKeyField. default False * many(_Optional_|bool)-determines if serializer serialize ManyToManyField. default False #### Usage: **datetime_format:** |parameters|intro| | -------------- | :---: | |string|convert datetime into string like "2015-05-10 10:19:22"| |timestamp|convert datetime into timestamp like "1432124420.0"| example: 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| | -------------- | :---: | |dict|convert data into dict or list| |json|convert data into json| |xml|convert data into xml| example: from dss.Serializer import serializer article_list = Article.objects.all()[0] data = serializer(article_list, output_type='xml') data: 0 first True first article first 0 1432392456.0 1432392456.0 31 **include_attr** example: 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** example: from dss.Serializer import serializer article_list = Article.objects.all() data = serializer(article_list, output_type='json', exclude_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** Serialize ForeignKeyField and its sub item example: 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** Serialize 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) No test data have ManyToManyField ,data format same as above #### dss.Mixin Serialize Mixin class JsonResponseMixin(object) datetime_type = 'string' # Output datetime format. Default is “string”,other parameters see dss.Serializer.serializer foreign = False # If serialize ForeignField。Default is False many = False # If serialize ManyToManyField。Default is False include_attr = None # Only serialize the attrs which in include_attr list。Default is None, accept a tuple contains attrs exclude_attr = None # serialize exclude attrs in exclude_attr list。Default is None, accept a tuple contains attrs #### Statement: Converts class based view into return json class based view,uses for DetailView and so on. #### Usage: example: # 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()), ) access:`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):* #### Statement: Mixin for ListView to converts it return data into json/xml. #### Usage: example: # 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()), ) access:`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):* #### Statement: Converts class based view into a return json data class based view,use for CreateView、UpdateView、FormView and so on. #### Usage: example: # 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()), ) access:`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": "" } ## 2.0.0 New Feature: Add serialize extra data: When we want to add extra data in model and serialize it, we can do like this: ```python 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) ``` The result will in "comments". The extra data can be a normal data type data, an other Django model, dict, list even a QuerySet. ## History ### Current Version:2.0.6 ##### 2017.03.22 v2.0.6: Add support for Python 3 ##### 2017.02.25 v2.0.5: Add support for Django model trough attribute ##### 2016.10.27 v2.0.4: Fix issue #2. ##### 2016.10.19 v2.0.3: Optimize code. Fix known bugs. Fix issue #1 ##### 2016.6.22 v2.0.2: Fix when dev in cbv, if include_attr is not None, MultipleJsonResponseMixin will filter all data. Fix datetime.datetime and datetime.time was formated as datetime.date Optimize code. ##### 2016.6.14 v2.0.1: fix known bugs. ##### 2016.6.13 v2.0.0: Rewrite serializer, optimizes serialize time. Fix known bugs. Add serialize support for all Django Field. New feature: add serialize extra data in model. ##### 2015.10.15 v1.0.0: Refactoring code. add cbv json minxin class. add serialize support for ManyToManyField. ##### 2015.10.12: v0.0.2: Fix bugs. ##### 2015.5.23: v0.0.1: First version. # License Copyright © RaPoSpectre. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: readme.md ================================================ # Django Simple Serializer --- [English Doc][1] Django Simple Serializer 是一个可以帮助开发者快速将 Django 数据或者 python data 序列化为 json|raw 数据。 ## 为什么要用 Django Simple Serializer ? 对于序列化 Django 数据的解决方案已经有以下几种: ### django.core.serializers Django内建序列化器, 它可以序列化Django model query set 但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 , 这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外, 如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。 ### QuerySet.values() 和上面一样, QuerySet.values() 同样没法工作如果你的model里有 DateTimeField 或者其他特殊的 Field 以及额外数据。 ### django-rest-framework serializers django-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。 他拥有完善的序列化器,但在使用之前你需要花费一些时间入门, 并学习 cbv 的开发方式, 对于有时间需求的项目显然这不是最好的解决方案。 ### django simple serializer 我希望可以快速简单的序列化数据, 所以我设计了一种可以不用任何额外的配置与学习而将Django data 或者 python data 序列化为相应的数据的简单的方式。 这就是为什么我写了 django simple serializer。 django simple serializer 的实际例子: [我的个人网站后台数据接口](https://github.com/bluedazzle/django-vue.js-blog/blob/master/api/views.py "22") ---------- ## 运行需求 ### Python 2: Django >= 1.5 Python >= 2.6 ### Python 3: Django >= 1.8 Python >= 3 ## 安装 Install using pip: pip install django-simple-serializer ## 使用 django simple serializer 进行开发 ### 序列化Django data 假设我们有以下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. ## 交流 **扫描二维码,验证信息输入 'dss' 或 '加群' 进入微信交流群** ![screenshot](https://raw.githubusercontent.com/bluedazzle/wechat_sender/master/qr.jpeg) ---------- ## API 手册 #### dss.Serializer 提供序列器 *function* serializer(*data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None, foreign=False, many=False, through=True*) #### Parameters: * 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))-不序列化 exclude_attr 列表里的字段。默认为 None * foreign(_Optional_|bool)-是否序列化 ForeignKeyField 。include_attr 与 exclude_attr 对 ForeignKeyField 依旧有效。 默认为 False * many(_Optional_|bool)-是否序列化 ManyToManyField 。include_attr 与 exclude_attr 对 ManyToManyField 依旧有效 默认为 False * through(_Optional_|bool)-是否序列化 ManyToManyField 中 through 属性数据 默认为 True #### 用法: **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', exclude_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 ,数据格式同上 #### dss.Mixin 提供序列器 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 through = True # 序列化 through 属性数据 #### 说明: 将普通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": "" } ## 2.0.0 新特点: 增加对额外数据的序列化支持: 当我们想在 model 中加入一些额外的数据并也想被序列化时, 现在可以这样做: ```python 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 ## 版本历史 ### 当前版本:2.0.7 ##### 2017.04.26 v2.0.7: 修复 FileField、ImageFdFile 序列化问题 ##### 2017.03.22 v2.0.6: 增加对 Python 3 的支持 ##### 2017.02.25 v2.0.5: 增加对 trough 属性支持 ##### 2016.10.27 v2.0.4: 修复 issue #2 ##### 2016.10.19 v2.0.3: 优化代码 修复已知 bug 修复 issue #1 ##### 2016.6.22 v2.0.2: 修复 cbv 下, 当有 include_attr 参数时, MultipleJsonResponseMixin 中所有数据被过滤的问题 修复 datetime.datetime 和 datetime.time 都被格式化为 datetime.date 数据 优化代码 ##### 2016.6.14 v2.0.1: 修复发布 bug ##### 2016.6.13 v2.0.0: 重写 serializer, 优化序列化速度; 修复已知 bug ; 增加对所有 Django Field 的支持; 新特性: 增加 model 额外数据的序列化支持 ##### 2015.10.15 v1.0.0: 重构代码,修复bug; 增加cbv json minxin 类 ; 增加对ManyToManyField序列化支持。 ##### 2015.10.12: v0.0.2: bug修复。 ##### 2015.5.23: v0.0.1: 第一版。 # License Copyright © RaPoSpectre. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [1]: https://github.com/bluedazzle/django-simple-serializer/blob/master/english_version.md ================================================ FILE: requirements.txt ================================================ django==1.8.2 xmltodict==0.9.2 future ================================================ FILE: src/README.rst ================================================ Django Simple Serializer ======================== -------------- [English Doc][1] Django Simple Serializer 是一个可以帮助开发者快速将 Django 数据或者 python data 序列化为 json\|raw 数据。 为什么要用 Django Simple Serializer ? ------------------------------------- 对于序列化 Django 数据的解决方案已经有以下几种: django.core.serializers ~~~~~~~~~~~~~~~~~~~~~~~ Django内建序列化器, 它可以序列化Django model query set 但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 , 这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外, 如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。 QuerySet.values() ~~~~~~~~~~~~~~~~~ 和上面一样, QuerySet.values() 同样没法工作如果你的model里有 DateTimeField 或者其他特殊的 Field 以及额外数据。 django-rest-framework serializers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ django-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。 他拥有完善的序列化器,但在使用之前你需要花费一些时间入门, 并学习 cbv 的开发方式, 对于有时间需求的项目显然这不是最好的解决方案。 django simple serializer ~~~~~~~~~~~~~~~~~~~~~~~~ 我希望可以快速简单的序列化数据, 所以我设计了一种可以不用任何额外的配置与学习而将Django data 或者 python data 序列化为相应的数据的简单的方式。 这就是为什么我写了 django simple serializer。 django simple serializer 的实际例子: `我的个人网站后台数据接口`_ -------------- 运行需求 -------- Python 2: ~~~~~~~~~ Django >= 1.5 Python >= 2.6 Python 3: ~~~~~~~~~ Django >= 1.8 Python >= 3 安装 ---- Install using pip: :: pip install django-simple-serializer 使用 django simple serializer 进行开发 -------------------------------------- 序列化Django data ~~~~~~~~~~~~~~~~~ 假设我们有以下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. -------------- API 手册 -------- dss.Serializer ^^^^^^^^^^^^^^ 提供序列器 *function* serializer(\ *data, datetime\_format=‘timestamp’, output\_type=‘raw’, include\_attr=None, exclude\_attr=None, foreign=False, many=False, through=True*) Parameters: ^^^^^^^^^^^ - 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))-不序列化 exclude\_attr 列表里的字段。默认为 None - foreign(\ *Optional*\ \|bool)-是否序列化 ForeignKeyField 。include\_attr 与 exclude\_attr 对 ForeignKeyField 依旧有效。 默认为 False - many(\ *Optional*\ \|bool)-是否序列化 ManyToManyField 。include\_attr 与 exclude\_attr 对 ManyToManyField 依旧有效 默认为 False - through(\ *Optional*\ \|bool)-是否序列化 ManyToManyField 中 through 属性数据 默认为 True .. _我的个人网站后台数据接口: https://github.com/bluedazzle/django-vue.js-blog/blob/master/api/views.py 用法: ^^^^^ **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 | +--------------+----------------------------------------------------+ [STRIKEOUT: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', exclude_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** ================================================ FILE: src/__init__.py ================================================ __author__ = 'RaPoSpectre' ================================================ FILE: src/dss/Mixin.py ================================================ # coding: utf-8 from __future__ import unicode_literals from __future__ import absolute_import import sys PY2 = True if sys.version < '3': from future.builtins import str, int PY2 = False import json from django.core.paginator import EmptyPage from .Serializer import serializer from .TimeFormatFactory import TimeFormatFactory try: from django.http import HttpResponse except ImportError: raise RuntimeError('django is required in django simple serializer') class JsonResponseMixin(object): datetime_type = 'string' foreign = False many = False include_attr = [] exclude_attr = [] def time_format(self, time_obj): time_func = TimeFormatFactory.get_time_func(self.datetime_type) return time_func(time_obj) def context_serialize(self, context, *args, **kwargs): try: context.pop('view') context.pop('object') except KeyError: pass except AttributeError: pass # if kwargs.get('multi_extend'): # self.include_attr.extend(kwargs.get('multi_extend')) return serializer(data=context, datetime_format=self.datetime_type, output_type='raw', foreign=self.foreign, many=self.many, include_attr=self.include_attr, exclude_attr=self.exclude_attr, dict_check=True) @staticmethod def json_serializer(context): return json.dumps(context, indent=4) def render_to_response(self, context, **response_kwargs): context_dict = self.context_serialize(context) json_context = self.json_serializer(context_dict) return HttpResponse(json_context, content_type='application/json', **response_kwargs) class FormJsonResponseMixin(JsonResponseMixin): def context_serialize(self, context, *args, **kwargs): form_list = [] form = context.get('form', None) if form: for itm in form.fields: f_dict = {'field': str(itm)} form_list.append(f_dict) context_dict = super(FormJsonResponseMixin, self).context_serialize(context, *args, **kwargs) context_dict['form'] = form_list return context_dict class MultipleJsonResponseMixin(JsonResponseMixin): def context_serialize(self, context, *args, **kwargs): # multi_extend = [i for i in context.keys() if not i.startswith('object') and i.endswith('_list')] # kwargs['multi_extend'] = multi_extend page_dict = {} is_paginated = context.get('is_paginated', None) if is_paginated: page_obj = context['page_obj'] page_dict['current'] = page_obj.number page_dict['total'] = page_obj.paginator.num_pages try: previous_page = page_obj.previous_page_number() except EmptyPage: previous_page = None try: next_page = page_obj.next_page_number() except EmptyPage: next_page = None page_dict['previous'] = previous_page page_dict['next'] = next_page page_dict['page_range'] = [{'page': i} for i in page_obj.paginator.page_range] try: context.pop('paginator') context.pop('object_list') except KeyError: pass except AttributeError: pass context_dict = super(MultipleJsonResponseMixin, self).context_serialize(context, *args, **kwargs) context_dict['page_obj'] = page_dict return context_dict ================================================ FILE: src/dss/Serializer.py ================================================ # coding: utf-8 from __future__ import unicode_literals import sys PY2 = True if sys.version < '3': from future.builtins import str, int PY2 = False import datetime import json from decimal import Decimal from .TimeFormatFactory import TimeFormatFactory try: from django.db import models from django.db.models import manager from django.core.paginator import Page from django.db.models.query import QuerySet from django.db.models.fields.files import ImageFieldFile, FileField except ImportError: raise RuntimeError('django is required in django simple serializer') class Serializer(object): include_attr = [] exclude_attr = [] objects = [] origin_data = None output_type = 'raw' datetime_format = 'timestamp' foreign = False many = False through = True def __init__(self, data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None, foreign=False, many=False, through=True, *args, **kwargs): if include_attr: self.include_attr = include_attr if exclude_attr: self.exclude_attr = exclude_attr self.origin_data = data self.output_type = output_type self.foreign = foreign self.many = many self.through = through self.through_fields = [] self.source_field = None self.datetime_format = datetime_format self.time_func = TimeFormatFactory.get_time_func(datetime_format) self._dict_check = kwargs.get('dict_check', False) def check_attr(self, attr): if self.exclude_attr and attr in self.exclude_attr: return False if self.include_attr and attr not in self.include_attr: return False return True def data_inspect(self, data, extra=None): if isinstance(data, (QuerySet, Page, list)): convert_data = [] if extra: for i, obj in enumerate(data): convert_data.append(self.data_inspect(obj, extra.get( **{self.through_fields[0]: obj, self.through_fields[1]: self.source_field}))) else: for obj in data: convert_data.append(self.data_inspect(obj)) return convert_data elif isinstance(data, models.Model): obj_dict = {} concrete_model = data._meta.concrete_model for field in concrete_model._meta.local_fields: if field.rel is None: if self.check_attr(field.name) and hasattr(data, field.name): obj_dict[field.name] = self.data_inspect(getattr(data, field.name)) else: if self.check_attr(field.name) and self.foreign: obj_dict[field.name] = self.data_inspect(getattr(data, field.name)) for field in concrete_model._meta.many_to_many: if self.check_attr(field.name) and self.many: obj_dict[field.name] = self.data_inspect(getattr(data, field.name)) for k, v in data.__dict__.items(): if not str(k).startswith('_') and k not in obj_dict.keys() and self.check_attr(k): obj_dict[k] = self.data_inspect(v) if extra: for field in extra._meta.concrete_model._meta.local_fields: if field.name not in obj_dict.keys() and field.name not in self.through_fields: if field.rel is None: if self.check_attr(field.name) and hasattr(extra, field.name): obj_dict[field.name] = self.data_inspect(getattr(extra, field.name)) else: if self.check_attr(field.name) and self.foreign: obj_dict[field.name] = self.data_inspect(getattr(extra, field.name)) return obj_dict elif isinstance(data, manager.Manager): through_list = data.through._meta.concrete_model._meta.local_fields through_data = data.through._default_manager self.through_fields = [data.target_field.name, data.source_field.name] self.source_field = data.instance if len(through_list) > 3 and self.through: return self.data_inspect(data.all(), through_data) else: return self.data_inspect(data.all()) elif isinstance(data, (datetime.datetime, datetime.date, datetime.time)): return self.time_func(data) elif isinstance(data, (ImageFieldFile, FileField)): return data.url if data.url else data.path elif isinstance(data, Decimal): return float(data) elif isinstance(data, dict): obj_dict = {} if self._dict_check: for k, v in data.items(): obj_dict[k] = self.data_inspect(v) else: for k, v in data.items(): if self.check_attr(k): obj_dict[k] = self.data_inspect(v) return obj_dict elif isinstance(data, (str, bool, float, int)): return data else: return None def data_format(self): self.objects = self.data_inspect(self.origin_data) def get_values(self): output_switch = {'dict': self.objects, 'raw': self.objects, 'json': json.dumps(self.objects, indent=4)} return output_switch.get(self.output_type, self.objects) def __call__(self): self.data_format() return self.get_values() def serializer(data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None, foreign=False, many=False, through=True, *args, **kwargs): s = Serializer(data, datetime_format, output_type, include_attr, exclude_attr, foreign, many, through, *args, **kwargs) return s() ================================================ FILE: src/dss/TimeFormatFactory.py ================================================ # coding: utf-8 import time import datetime from functools import partial try: from django.utils import timezone except ImportError: raise RuntimeError('Django is required for django simple serializer.') class TimeFormatFactory(object): def __init__(self): super(TimeFormatFactory, self).__init__() @staticmethod def datetime_to_string(datetime_time, time_format='%Y-%m-%d %H:%M:%S'): if isinstance(datetime_time, datetime.datetime): if datetime_time.tzinfo: datetime_time = datetime_time.astimezone(timezone.get_current_timezone()) return datetime_time.strftime(time_format) elif isinstance(datetime_time, datetime.time): time_format = '%H:%M:%S' elif isinstance(datetime_time, datetime.date): time_format = '%Y-%m-%d' return datetime_time.strftime(time_format) @staticmethod def datetime_to_timestamp(datetime_time, time_format=None): if isinstance(datetime_time, datetime.datetime): if datetime_time.tzinfo: datetime_time = datetime_time.astimezone(timezone.get_current_timezone()) return time.mktime(datetime_time.timetuple()) return time.mktime(datetime_time.timetuple()) @staticmethod def get_time_func(func_type='string'): if func_type == 'string': return TimeFormatFactory.datetime_to_string elif func_type == 'timestamp': return TimeFormatFactory.datetime_to_timestamp else: return TimeFormatFactory.datetime_to_string ================================================ FILE: src/dss/Warning.py ================================================ from __future__ import unicode_literals import warnings class RemovedInNextVersionWarning(DeprecationWarning): pass def remove_check(**kwargs): deep = kwargs.get('deep', None) if deep is not None: warnings.warn('Parameter "deep" will removed in next version!', RemovedInNextVersionWarning, stacklevel=2) return deep return None ================================================ FILE: src/dss/__init__.py ================================================ __author__ = 'RaPoSpectre' ================================================ FILE: src/setup.py ================================================ import codecs import os import sys try: from setuptools import setup except ImportError: from distutils.core import setup def read(fname): return codecs.open(os.path.join(os.path.dirname(__file__), fname)).read() NAME = "django-simple-serializer" PACKAGES = ["dss", ] DESCRIPTION = "Django Simple Serializer is a serializer to help user serialize django data or python list into json,xml,dict data in a simple way." LONG_DESCRIPTION = read("README.rst") KEYWORDS = "django serializer" AUTHOR = "RaPoSpectre" AUTHOR_EMAIL = "rapospectre@gmail.com" URL = "https://github.com/bluedazzle/django-simple-serializer" VERSION = "2.0.7" LICENSE = "MIT" setup( name=NAME, version=VERSION, description=DESCRIPTION, long_description=LONG_DESCRIPTION, classifiers=[ 'License :: OSI Approved :: MIT License', 'Programming Language :: Python', 'Intended Audience :: Developers', 'Operating System :: OS Independent', ], install_requires=[ 'future' ], keywords=KEYWORDS, author=AUTHOR, author_email=AUTHOR_EMAIL, url=URL, license=LICENSE, packages=PACKAGES, include_package_data=True, zip_safe=True, ) ================================================ FILE: src/test/__init__.py ================================================ __author__ = 'RaPoSpectre' ================================================ FILE: src/test/test_Mixin.py ================================================ # coding: utf-8 from __future__ import unicode_literals from __future__ import absolute_import import json from unittest import TestCase from ..dss.Mixin import JsonResponseMixin, FormJsonResponseMixin, MultipleJsonResponseMixin import datetime class TestJsonResponseMixin(TestCase): def setUp(self): self.json_mixin = JsonResponseMixin() self.json_mixin.datetime_type = 'string' def test_time_format(self): res = self.json_mixin.time_format(datetime.datetime(2015, 12, 12, 12)) self.assertEqual(res, '2015-12-12 12:00:00') def test_render_to_response(self): context = {'title': 'test', 'name': 'test_name'} resp = self.json_mixin.render_to_response(context=context) self.assertEqual(resp.content, json.dumps(context, indent=4)) class TestFormJsonResponseMixin(TestCase): def setUp(self): self.form_mixin = FormJsonResponseMixin() self.form_mixin.datetime_type = 'string' class TestForm(object): fields = ['form1', 'form2', 'form3'] self.form = TestForm() def test_context_serialize(self): context = {'title': 'test_title', 'form': self.form} result = self.form_mixin.context_serialize(context) expect_res = {'title': 'test_title', 'form': [{'field': 'form1'}, {'field': 'form2'}, {'field': 'form3'}]} self.assertEqual(result, expect_res) class TestMultipleJsonResponseMixin(TestCase): def setUp(self): self.multi_mixin = MultipleJsonResponseMixin() class TestPaginator(object): pass class TestPage(object): number = 1 paginator = TestPaginator() setattr(paginator, 'num_pages', 3) setattr(paginator, 'page_range', [1, 2, 3]) def previous_page_number(self): return None def next_page_number(self): return 2 self.page_obj = TestPage() def test_context_serialize(self): context = {'page_obj': self.page_obj, 'is_paginated': True, 'title': 'test'} result = self.multi_mixin.context_serialize(context) expect_res = {'current': 1, 'total': 3, 'previous': None, 'next': 2, 'page_range': [{'page': 1}, {'page': 2}, {'page': 3}]} self.assertEqual(result['page_obj'], expect_res) ================================================ FILE: src/test/test_Serializer.py ================================================ # coding: utf-8 from __future__ import unicode_literals import json from unittest import TestCase import datetime from django.db import models from django.conf import settings from dss.TimeFormatFactory import TimeFormatFactory from dss.Serializer import serializer __author__ = 'RaPoSpectre' class Test_Serializer(TestCase): def setUp(self): self.time_func = TimeFormatFactory.get_time_func('string') # DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': ':memory:', # 'USER': '', # Not used with sqlite3. # 'PASSWORD': '', # Not used with sqlite3. # 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. # 'PORT': '', # } # } # settings.configure(DATABASES=DATABASES, DEBUG=True) # class TestAuthor(models.Model): # name = models.CharField(default='test_author') # # def __unicode__(self): # return self.name # # class TestTags(models.Model): # tag = models.CharField(default='test_tag') # create_time = models.DateTimeField(auto_now=True) # # class TestArticle(models.Model): # title = models.CharField(default='test') # content = models.CharField(default='test') # author = models.ForeignKey(TestAuthor, related_name='author_art') # tags = models.ManyToManyField(TestTags, related_name='tag_art') # create_time = models.DateTimeField(auto_now=True) # # # self.author = TestAuthor() # self.author.save() # tags = TestTags(tag='tag1') # tags.save() # self.article = TestArticle(author=self.author) # self.article.tags.add(tags) # self.article.save() def test_serializer(self): test_data = {'title': 'test', 'name': 'attr', 'time': datetime.datetime(2015, 10, 10, 12), 'list': [{'content': 'list_content', 'time': datetime.datetime(2015, 10, 11, 9)}, {'content': 'list_content1', 'time': datetime.datetime(2015, 12, 22, 9)}]} result = serializer(test_data, datetime_format='string', output_type='raw') self.assertEqual(result['time'], '2015-10-10 12:00:00') self.assertIsInstance(result, dict) self.assertEqual(result['list'][0]['time'], '2015-10-11 09:00:00') result = serializer(test_data, datetime_format='timestamp', output_type='json') self.assertEqual(json.loads(result)['title'], 'test') self.assertEqual(json.loads(result)['list'][0]['content'], 'list_content') ================================================ FILE: src/test/test_TimeFormatFactory.py ================================================ import unittest import datetime from ..dss.TimeFormatFactory import TimeFormatFactory class TestTimeFormatFactory(unittest.TestCase): def setUp(self): self.time_factory = TimeFormatFactory() def test_create_string(self): new_time = datetime.datetime(2015, 5, 20, 20, 20, 20) time_func = self.time_factory.get_time_func('string') time_str = time_func(new_time) self.assertEqual(time_str, '2015-05-20 20:20:20') def test_create_timestamp(self): new_time = datetime.datetime(2015, 5, 20, 20, 20, 20) time_func = self.time_factory.get_time_func('timestamp') time_stamp = time_func(new_time) self.assertEqual(time_stamp, 1432124420.0) def test_get_time_func(self): time_func = self.time_factory.get_time_func('string') time_str = time_func(datetime.datetime(1999, 9, 9, 9)) self.assertEqual(time_str, '1999-09-09 09:00:00') if __name__ == '__main__': unittest.main()