[
  {
    "path": ".gitignore",
    "content": "*.pyc\n*.pyo\n*.sqlite3\n.idea/\n.idea\n.DS_Store\nsrc/django_simple_serializer.egg-info/\nsrc/dist/\nsrc/build/\n.coverage\nfabfile.py"
  },
  {
    "path": ".travis.yml",
    "content": "language: python\npython:\n  - \"2.6\"\n  - \"2.7\"\n  - \"3.2\"\n  - \"3.3\"\n  - \"3.4\"\n  - \"3.5\"\n  - \"3.5-dev\" # 3.5 development branch\n  - \"nightly\" # currently points to 3.6-dev\n# command to install dependencies\ninstall: \"pip install -r requirements.txt\"\n# command to run tests\nscript: nosetests"
  },
  {
    "path": "LICENSE",
    "content": "Copyright © RaPoSpectre.\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "english_version.md",
    "content": "# Django Simple Serializer\n\n---\n\nDjango Simple Serializer is a serializer to help user serialize django data or python list into json\\xml\\dict data in a simple way.\n\n## Why Django Simple Serializer ?\n\n\n### django.core.serializers\n 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)\n### QuerySet.values()\n As above, QuerySet.values() also not work well if you have DateTimeField into your model.\n### django-rest-framework serializers\n 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. \n### django simple serializer\nFor 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.\n\n## Requirements\n\n### Python 2:\n\nDjango >= 1.5\n\nPython >= 2.6\n\n### Python 3:\n\nDjango >= 1.8\n\nPython >= 3\n\n## Installation\n\nInstall using pip:\n\n    pip install django-simple-serializer\n\n## Working with django simple serializer\n### Serializing objects\nAssuming that we have django models like these:\n\n    class Classification(models.Model):\n        c_name = models.CharField(max_length=30, unique=True)\n    \n    class Article(models.Model):\n        caption = models.CharField(max_length=50)\n        classification = models.ForeignKey(Classification, related_name='cls_art')\n        content = models.TextField()\n        publish = models.BooleanField(default=False)\n\na simple example with using django models above:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list)\n\ndata:\n\n    [{'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}]\n\nBy 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.\n\n## API Guide\n\n#### dss.Serializer\nProvides the serializer\n\n*function* serializer(*data, datetime_format='timestamp', output_type='dict', include_attr=None, exclude_attr=None, deep=False*)\n\n#### Parameters:\n\n* data(_Required_|(QuerySet, Page, list, django model object))-data to be processed\n* datetime_format(_Optional_|string)-convert datetime into string.default \"timestamp\"\n* output_type(_Optional_|string)-serialize type. default \"dict\"\n* include_attr(_Optional_|(list, tuple))-only serialize attributes in include_attr list. default None\n* exclude_attr(_Optional_|(list, tuple))-exclude attributes in exclude_attr list. default None\n* foreign(_Optional_|bool)-determines if serializer serialize ForeignKeyField. default False\n* many(_Optional_|bool)-determines if serializer serialize ManyToManyField. default False\n\n#### Usage:\n\n**datetime_format:**  \n\n|parameters|intro|\n| --------------  | :---: |\n|string|convert datetime into string like \"2015-05-10 10:19:22\"|\n|timestamp|convert datetime into timestamp like \"1432124420.0\"|  \n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, datetime_format='string', output_type='json')\n\ndata:\n\n    [\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"first\",\n            \"publish\": true,\n            \"content\": \"first article\",\n            \"caption\": \"first\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:47:36\",\n            \"modify_time\": \"2015-05-23 22:47:36\",\n            \"id\": 31\n        },\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"second\",\n            \"publish\": false,\n            \"content\": \"second article\",\n            \"caption\": \"second\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:48:19\",\n            \"modify_time\": \"2015-05-23 22:48:19\",\n            \"id\": 32\n        }\n    ]\n\n**output_type**  \n\n|parameters|intro|\n| --------------  | :---: |\n|dict|convert data into dict or list|\n|json|convert data into json|\n|xml|convert data into xml|  \n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()[0]\n    data = serializer(article_list, output_type='xml')\n\ndata:  \n\n    <?xml version=\"1.0\" encoding=\"utf-8\"?>\n    <root>\n        <read_count>0</read_count>\n        <sub_caption>first</sub_caption>\n        <publish>True</publish>\n        <content>first article</content>\n        <caption>first</caption>\n        <comment_count>0</comment_count>\n        <create_time>1432392456.0</create_time>\n        <modify_time>1432392456.0</modify_time>\n        <id>31</id>\n    </root>  \n\n**include_attr**\n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('content', 'caption',))\n\ndata:  \n\n    [\n        {\n            \"content\": \"first article\",\n            \"caption\": \"first\"\n        },\n        {\n            \"content\": \"second article\",\n            \"caption\": \"second\"\n        }\n    ]\n\n**exclude_attr**\n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', exclude_attr=('content',))\n\ndata:  \n\n        [\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"first\",\n                \"publish\": true,\n                \"caption\": \"first\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392456,\n                \"modify_time\": 1432392456,\n                \"id\": 31\n            },\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"second\",\n                \"publish\": false,\n                \"caption\": \"second\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392499,\n                \"modify_time\": 1432392499,\n                \"id\": 32\n            }\n        ]\n        \n**foreign**\n\nSerialize ForeignKeyField and its sub item\n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('classification', 'caption', 'create_time', foreign=True)\n\ndata:  \n\n        [\n            {\n                \"caption\": \"first\",\n                \"create_time\": 1432392456,\n                \"classification\": {\n                    \"create_time\": 1429708506,\n                    \"c_name\": \"python\",\n                    \"id\": 1,\n                    \"modify_time\": 1429708506\n                }\n            },\n            {\n                \"caption\": \"second\",\n                \"create_time\": 1432392499,\n                \"classification\": {\n                    \"create_time\": 1430045890,\n                    \"c_name\": \"test\",\n                    \"id\": 5,\n                    \"modify_time\": 1430045890\n                }\n            }\n        ]\n\n**many**\nSerialize ManyToManyField\n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('classification', 'caption', 'create_time', many=True)\n\nNo test data have ManyToManyField ，data format same as above\n\n#### dss.Mixin\nSerialize Mixin\n\n    class JsonResponseMixin(object)\n        datetime_type = 'string'                # Output datetime format. Default is “string”，other parameters see dss.Serializer.serializer\n        foreign = False                         # If serialize ForeignField。Default is False\n        many = False                            # If serialize ManyToManyField。Default is False\n        include_attr = None                     # Only serialize the  attrs which in include_attr list。Default is None, accept a tuple contains attrs\n        exclude_attr = None                     # serialize exclude attrs in exclude_attr list。Default is None, accept a tuple contains attrs\n\n#### Statement:\n\nConverts class based view into return json class based view，uses for DetailView and so on.\n\n#### Usage:\n\nexample:\n\n    # view.py\n    from dss.Mixin import JsonResponseMixin\n    from django.views.generic import DetailView\n    from model import Article\n    \n    class TestView(JsonResponseMixin, DetailView):\n        model = Article\n        datetime_type = 'string'\n        pk_url_kwarg = 'id'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/(?P<id>(\\d)+)/$', TestView.as_view()),\n    )\n        \naccess：`localhost:8000/test/1/`\n\nresponse:\n\n    {\n        \"article\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"comments\": [], \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"object\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"comments\": [], \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"view\": \"\"\n    }\n\n\n*class MultipleJsonResponseMixin(JsonResponseMixin):*\n\n#### Statement:\n\nMixin for ListView to converts it return data into json/xml.\n\n#### Usage:\n\nexample:\n\n    # view.py\n    from dss.Mixin import MultipleJsonResponseMixin\n    from django.views.generic import ListView\n    from model import Article\n    \n    class TestView(MultipleJsonResponseMixin, ListView):\n        model = Article\n        query_set = Article.objects.all()\n        paginate_by = 1\n        datetime_type = 'string'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/$', TestView.as_view()),\n    )\n        \naccess：`localhost:8000/test/`\n\nresponse:\n\n    {\n        \"paginator\": \"\", \n        \"article_list\": [\n            {\n                \"classification_id\": 1, \n                \"read_count\": 2, \n                \"sub_caption\": \"first\", \n                \"content\": \"first article\", \n                \"caption\": \"first\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 31\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"\", \n                \"content\": \"testseteset\", \n                \"caption\": \"hehe\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 33\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"second\", \n                \"content\": \"asdfasdfasdf\", \n                \"caption\": \"second\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 32\n            }\n        ], \n        \"object_list\": [\n            {\n                \"classification_id\": 1, \n                \"read_count\": 2, \n                \"sub_caption\": \"first\", \n                \"content\": \"first article\", \n                \"caption\": \"first\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 31\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"\", \n                \"content\": \"testseteset\", \n                \"caption\": \"hehe\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 33\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"second\", \n                \"content\": \"asdfasdfasdf\", \n                \"caption\": \"second\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 32\n            }\n        ], \n        \"page_obj\": {\n            \"current\": 1, \n            \"next\": 2, \n            \"total\": 3, \n            \"page_range\": [\n                {\n                    \"page\": 1\n                }, \n                {\n                    \"page\": 2\n                }, \n                {\n                    \"page\": 3\n                }\n            ], \n            \"previous\": null\n        }, \n        \"is_paginated\": true, \n        \"view\": \"\"\n    }\n\n*class FormJsonResponseMixin(JsonResponseMixin):*\n\n#### Statement:\n\nConverts class based view into a return json data class based view，use for CreateView、UpdateView、FormView and so on.\n\n#### Usage:\n\nexample:\n\n    # view.py\n    from dss.Mixin import FormJsonResponseMixin\n    from django.views.generic import UpdateView\n    from model import Article\n    \n    class TestView(FormJsonResponseMixin, UpdateView):\n        model = Article\n        datetime_type = 'string'\n        pk_url_kwarg = 'id'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/(?P<id>(\\d)+)/$', TestView.as_view()),\n    )\n        \naccess：`localhost:8000/test/1/`\n\nresponse:\n\n    {\n        \"article\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"form\": [\n            {\n                \"field\": \"caption\"\n            }, \n            {\n                \"field\": \"sub_caption\"\n            }, \n            {\n                \"field\": \"read_count\"\n            }, \n            {\n                \"field\": \"comment_count\"\n            }, \n            {\n                \"field\": \"classification\"\n            }, \n            {\n                \"field\": \"content\"\n            }, \n            {\n                \"field\": \"publish\"\n            }\n        ], \n        \"object\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"view\": \"\"\n    }\n## 2.0.0 New Feature:\nAdd serialize extra data:\n\nWhen we want to add extra data in model and serialize it, we can do like this:\n\n```python\n    def add_extra(article):\n        comments = Comment.objects.filter(article=article)\n        setattr(article, 'comments', comments)\n    \n    articles = Article.objects.all()\n    map(add_extra, articles)\n    result = serializer(articles)\n```\n\nThe result will in \"comments\".\n\nThe extra data can be a normal data type data, an other Django model, dict, list even a QuerySet.\n\n\n## History\n\n### Current Version：2.0.6\n\n##### 2017.03.22 v2.0.6:\n\nAdd support for Python 3\n\n##### 2017.02.25 v2.0.5:\n\nAdd support for Django model trough attribute\n\n##### 2016.10.27 v2.0.4:\n\nFix issue #2.\n \n##### 2016.10.19 v2.0.3:\nOptimize code.\n\nFix known bugs.\n\nFix issue #1\n\n##### 2016.6.22 v2.0.2:\n\nFix when dev in cbv, if include_attr is not None, MultipleJsonResponseMixin will filter all data.\n\nFix datetime.datetime and datetime.time was formated as datetime.date  \n\nOptimize code.\n\n##### 2016.6.14 v2.0.1:\n\nfix known bugs.\n\n##### 2016.6.13 v2.0.0:\n\nRewrite serializer, optimizes serialize time. \n\nFix known bugs. \n\nAdd serialize support for all Django Field. \n\nNew feature: add serialize extra data in model.\n\n##### 2015.10.15 v1.0.0:\nRefactoring code. \n\nadd cbv json minxin class. \n\nadd serialize support for ManyToManyField.\n\n##### 2015.10.12: v0.0.2:\n\nFix bugs.\n\n##### 2015.5.23: v0.0.1:\n\nFirst version.\n\n# License\n\nCopyright © RaPoSpectre.\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "readme.md",
    "content": "# Django Simple Serializer\n\n---\n\n[English Doc][1]\n\nDjango Simple Serializer 是一个可以帮助开发者快速将 Django 数据或者 python data 序列化为 json|raw 数据。\n\n## 为什么要用 Django Simple Serializer ?\n\n对于序列化 Django 数据的解决方案已经有以下几种：  \n\n### django.core.serializers\n Django内建序列化器, 它可以序列化Django model query set 但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 , 这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外, 如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。\n### QuerySet.values()\n 和上面一样, QuerySet.values() 同样没法工作如果你的model里有 DateTimeField 或者其他特殊的 Field 以及额外数据。\n### django-rest-framework serializers\n django-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。 他拥有完善的序列化器，但在使用之前你需要花费一些时间入门, 并学习 cbv 的开发方式, 对于有时间需求的项目显然这不是最好的解决方案。\n### django simple serializer\n我希望可以快速简单的序列化数据, 所以我设计了一种可以不用任何额外的配置与学习而将Django data 或者 python data 序列化为相应的数据的简单的方式。 这就是为什么我写了 django simple serializer。\n\ndjango simple serializer 的实际例子: [我的个人网站后台数据接口](https://github.com/bluedazzle/django-vue.js-blog/blob/master/api/views.py \"22\") \n\n----------\n\n## 运行需求\n\n### Python 2:\n\nDjango >= 1.5\n\nPython >= 2.6\n\n### Python 3:\n\nDjango >= 1.8\n\nPython >= 3\n\n## 安装\n\nInstall using pip:\n\n    pip install django-simple-serializer\n\n## 使用 django simple serializer 进行开发\n### 序列化Django data\n假设我们有以下Django models：\n\n    class Classification(models.Model):\n        c_name = models.CharField(max_length=30, unique=True)\n    \n    class Article(models.Model):\n        caption = models.CharField(max_length=50)\n        classification = models.ForeignKey(Classification, related_name='cls_art')\n        content = models.TextField()\n        publish = models.BooleanField(default=False)\n\n使用django simple serializer的简单例子：\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list)\n\ndata:\n\n    [{'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}]\n\n默认情况下, 序列器会返回一个 list 或者 dict(对于单个model实例), 你可以设置参数 “output_type” 来决定序列器返回 json/raw.\n\n\n## 交流\n\n**扫描二维码，验证信息输入 'dss' 或 '加群' 进入微信交流群**\n\n![screenshot](https://raw.githubusercontent.com/bluedazzle/wechat_sender/master/qr.jpeg)\n\n----------\n\n## API 手册\n\n#### dss.Serializer\n提供序列器\n\n*function* serializer(*data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None, foreign=False, many=False, through=True*)\n\n#### Parameters:\n\n* data(_Required_|(QuerySet, Page, list, django model object))-待处理数据\n* datetime_format(_Optional_|string)-如果包含 datetime 将 datetime 转换成相应格式.默认为 \"timestamp\"（时间戳）\n* output_type(_Optional_|string)-serialize type. 默认“raw”原始数据，即返回list或dict\n* include_attr(_Optional_|(list, tuple))-只序列化 include_attr 列表里的字段。默认为 None\n* exclude_attr(_Optional_|(list, tuple))-不序列化 exclude_attr 列表里的字段。默认为 None\n* foreign(_Optional_|bool)-是否序列化 ForeignKeyField 。include_attr 与 exclude_attr 对   ForeignKeyField 依旧有效。 默认为 False\n* many(_Optional_|bool)-是否序列化 ManyToManyField 。include_attr 与 exclude_attr 对 ManyToManyField 依旧有效 默认为 False\n* through(_Optional_|bool)-是否序列化 ManyToManyField 中 through 属性数据 默认为 True\n\n#### 用法:\n\n**datetime_format:**  \n\n|parameters|intro|\n| --------------  | :---: |\n|string|转换 datetime 为字符串。如： \"2015-05-10 10:19:22\"|\n|timestamp|转换 datetime 为时间戳。如： \"1432124420.0\"|  \n\n例子:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, datetime_format='string', output_type='json')\n\ndata:\n\n    [\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"first\",\n            \"publish\": true,\n            \"content\": \"first article\",\n            \"caption\": \"first\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:47:36\",\n            \"modify_time\": \"2015-05-23 22:47:36\",\n            \"id\": 31\n        },\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"second\",\n            \"publish\": false,\n            \"content\": \"second article\",\n            \"caption\": \"second\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:48:19\",\n            \"modify_time\": \"2015-05-23 22:48:19\",\n            \"id\": 32\n        }\n    ]\n\n**output_type**  \n\n|parameters|intro|\n| --------------  | :---: |\n|raw|将list或dict中的特殊对象序列化后输出为list或dict|\n|dict|同 raw|  \n|json|转换数据为 json|\n\n~~xml 转换数据为 xml~~  (暂时去除)\n\n例子:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()[0]\n    data = serializer(article_list, output_type='json')\n\ndata:  \n\n    {\n            \"read_count\": 0,\n            \"sub_caption\": \"first\",\n            \"publish\": true,\n            \"content\": \"first article\",\n            \"caption\": \"first\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:47:36\",\n            \"modify_time\": \"2015-05-23 22:47:36\",\n            \"id\": 31\n        }\n\n**include_attr**\n\n例子:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('content', 'caption',))\n\ndata:  \n\n    [\n        {\n            \"content\": \"first article\",\n            \"caption\": \"first\"\n        },\n        {\n            \"content\": \"second article\",\n            \"caption\": \"second\"\n        }\n    ]\n\n**exclude_attr**\n\n例子:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', exclude_attr=('content',))\n\ndata:  \n\n        [\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"first\",\n                \"publish\": true,\n                \"caption\": \"first\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392456,\n                \"modify_time\": 1432392456,\n                \"id\": 31\n            },\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"second\",\n                \"publish\": false,\n                \"caption\": \"second\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392499,\n                \"modify_time\": 1432392499,\n                \"id\": 32\n            }\n        ]\n        \n**foreign**\n\n序列化数据中的 ForeignKeyField 及其子项目\n\n例子:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('classification', 'caption', 'create_time', foreign=True)\n\ndata:  \n\n        [\n            {\n                \"caption\": \"first\",\n                \"create_time\": 1432392456,\n                \"classification\": {\n                    \"create_time\": 1429708506,\n                    \"c_name\": \"python\",\n                    \"id\": 1,\n                    \"modify_time\": 1429708506\n                }\n            },\n            {\n                \"caption\": \"second\",\n                \"create_time\": 1432392499,\n                \"classification\": {\n                    \"create_time\": 1430045890,\n                    \"c_name\": \"test\",\n                    \"id\": 5,\n                    \"modify_time\": 1430045890\n                }\n            }\n        ]\n\n**many**\n序列化 ManyToManyField\n\nexample:\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('classification', 'caption', 'create_time', many=True)\n\n测试数据无 ManyToManyField ，数据格式同上\n\n#### dss.Mixin\n提供序列器 Mixin\n\n    class JsonResponseMixin(object)\n        datetime_type = 'string'                # 输出datetime时间格式。默认为“string”，可选参数相见dss.Serializer.serializer\n        foreign = False                         # 是否序列化ForeignField。默认为False\n        many = False                            # 是否序列化ManyToManyField。默认为False\n        include_attr = None                     # 只序列化include_attr包含的属性。默认为None,接受一个包含属性名称的tuple\n        exclude_attr = None                     # 不序列化exclude_attr包含的属性。默认为None,接受一个包含属性名称的tuple\n        through = True                          # 序列化 through 属性数据\n\n#### 说明:\n\n将普通class based view 转换为返回json数据的class based view，适用于DetailView等\n\n#### 用法:\n\n例子:\n\n    # view.py\n    from dss.Mixin import JsonResponseMixin\n    from django.views.generic import DetailView\n    from model import Article\n    \n    class TestView(JsonResponseMixin, DetailView):\n        model = Article\n        datetime_type = 'string'\n        pk_url_kwarg = 'id'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/(?P<id>(\\d)+)/$', TestView.as_view()),\n    )\n        \n访问：`localhost:8000/test/1/`\n\nresponse:\n\n    {\n        \"article\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"comments\": [], \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"object\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"comments\": [], \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"view\": \"\"\n    }\n\n\n*class MultipleJsonResponseMixin(JsonResponseMixin):*\n\n#### 说明:\n\n将列表类视图转换为返回json数据的类视图，适用于ListView等\n\n#### 用法:\n\n例子:\n\n    # view.py\n    from dss.Mixin import MultipleJsonResponseMixin\n    from django.views.generic import ListView\n    from model import Article\n    \n    class TestView(MultipleJsonResponseMixin, ListView):\n        model = Article\n        query_set = Article.objects.all()\n        paginate_by = 1\n        datetime_type = 'string'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/$', TestView.as_view()),\n    )\n        \n访问：`localhost:8000/test/`\n\nresponse:\n\n    {\n        \"paginator\": \"\", \n        \"article_list\": [\n            {\n                \"classification_id\": 1, \n                \"read_count\": 2, \n                \"sub_caption\": \"first\", \n                \"content\": \"first article\", \n                \"caption\": \"first\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 31\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"\", \n                \"content\": \"testseteset\", \n                \"caption\": \"hehe\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 33\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"second\", \n                \"content\": \"asdfasdfasdf\", \n                \"caption\": \"second\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 32\n            }\n        ], \n        \"object_list\": [\n            {\n                \"classification_id\": 1, \n                \"read_count\": 2, \n                \"sub_caption\": \"first\", \n                \"content\": \"first article\", \n                \"caption\": \"first\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 31\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"\", \n                \"content\": \"testseteset\", \n                \"caption\": \"hehe\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 33\n            }, \n            {\n                \"classification_id\": 5, \n                \"read_count\": 0, \n                \"sub_caption\": \"second\", \n                \"content\": \"asdfasdfasdf\", \n                \"caption\": \"second\", \n                \"comment_count\": 0, \n                \"publish\": false, \n                \"id\": 32\n            }\n        ], \n        \"page_obj\": {\n            \"current\": 1, \n            \"next\": 2, \n            \"total\": 3, \n            \"page_range\": [\n                {\n                    \"page\": 1\n                }, \n                {\n                    \"page\": 2\n                }, \n                {\n                    \"page\": 3\n                }\n            ], \n            \"previous\": null\n        }, \n        \"is_paginated\": true, \n        \"view\": \"\"\n    }\n\n*class FormJsonResponseMixin(JsonResponseMixin):*\n\n#### 说明:\n\n将普通class based view 转换为返回json数据的class based view，适用于CreateView、UpdateView、FormView等\n\n#### 用法:\n\n例子:\n\n    # view.py\n    from dss.Mixin import FormJsonResponseMixin\n    from django.views.generic import UpdateView\n    from model import Article\n    \n    class TestView(FormJsonResponseMixin, UpdateView):\n        model = Article\n        datetime_type = 'string'\n        pk_url_kwarg = 'id'\n    \n    \n    # urls.py\n    from view import TestView\n    urlpatterns = patterns('',\n        url(r'^test/(?P<id>(\\d)+)/$', TestView.as_view()),\n    )\n        \n访问：`localhost:8000/test/1/`\n\nresponse:\n\n    {\n        \"article\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"form\": [\n            {\n                \"field\": \"caption\"\n            }, \n            {\n                \"field\": \"sub_caption\"\n            }, \n            {\n                \"field\": \"read_count\"\n            }, \n            {\n                \"field\": \"comment_count\"\n            }, \n            {\n                \"field\": \"classification\"\n            }, \n            {\n                \"field\": \"content\"\n            }, \n            {\n                \"field\": \"publish\"\n            }\n        ], \n        \"object\": {\n            \"classification_id\": 5, \n            \"read_count\": 0, \n            \"sub_caption\": \"second\", \n            \"content\": \"asdfasdfasdf\", \n            \"caption\": \"second\", \n            \"comment_count\": 0, \n            \"id\": 32, \n            \"publish\": false\n        }, \n        \"view\": \"\"\n    }\n## 2.0.0 新特点:\n增加对额外数据的序列化支持:\n\n当我们想在 model 中加入一些额外的数据并也想被序列化时, 现在可以这样做:\n\n```python\n    def add_extra(article):\n        comments = Comment.objects.filter(article=article)\n        setattr(article, 'comments', comments)\n    \n    articles = Article.objects.all()\n    map(add_extra, articles)\n    result = serializer(articles)\n```\n\n序列化的结果数据中将会包含\"comments\"哦.\n\n额外加入的数据可以是一个普通的数据类型、 另一个 Django model、 字典、 列表甚至 QuerySet\n\n\n## 版本历史\n\n### 当前版本：2.0.7\n\n##### 2017.04.26 v2.0.7:\n\n修复 FileField、ImageFdFile 序列化问题\n\n##### 2017.03.22 v2.0.6:\n\n增加对 Python 3 的支持\n\n##### 2017.02.25 v2.0.5:\n\n增加对 trough 属性支持\n\n##### 2016.10.27 v2.0.4:\n\n修复 issue #2\n \n##### 2016.10.19 v2.0.3:\n优化代码\n\n修复已知 bug\n\n修复 issue #1\n\n##### 2016.6.22 v2.0.2:\n\n修复 cbv 下, 当有 include_attr 参数时, MultipleJsonResponseMixin 中所有数据被过滤的问题 \n\n修复 datetime.datetime 和 datetime.time 都被格式化为 datetime.date 数据 \n\n优化代码\n\n##### 2016.6.14 v2.0.1:\n\n修复发布 bug\n\n##### 2016.6.13 v2.0.0:\n\n重写 serializer, 优化序列化速度; \n\n修复已知 bug ; \n\n增加对所有 Django Field 的支持; \n\n新特性: 增加 model 额外数据的序列化支持\n\n##### 2015.10.15 v1.0.0:\n重构代码，修复bug； \n\n增加cbv json minxin 类 ； \n\n增加对ManyToManyField序列化支持。\n\n##### 2015.10.12: v0.0.2:\n\nbug修复。\n\n##### 2015.5.23: v0.0.1:\n\n第一版。\n\n# License\n\nCopyright © RaPoSpectre.\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this\nlist of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this\nlist of conditions and the following disclaimer in the documentation and/or\nother materials provided with the distribution.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n[1]: https://github.com/bluedazzle/django-simple-serializer/blob/master/english_version.md\n\n\n\n\n"
  },
  {
    "path": "requirements.txt",
    "content": "django==1.8.2\nxmltodict==0.9.2\nfuture"
  },
  {
    "path": "src/README.rst",
    "content": "Django Simple Serializer\n========================\n\n--------------\n\n[English Doc][1]\n\nDjango Simple Serializer 是一个可以帮助开发者快速将 Django 数据或者\npython data 序列化为 json\\|raw 数据。\n\n为什么要用 Django Simple Serializer ?\n-------------------------------------\n\n对于序列化 Django 数据的解决方案已经有以下几种：\n\ndjango.core.serializers\n~~~~~~~~~~~~~~~~~~~~~~~\n\nDjango内建序列化器, 它可以序列化Django model query set\n但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 ,\n这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外,\n如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。\n\nQuerySet.values()\n~~~~~~~~~~~~~~~~~\n\n和上面一样, QuerySet.values() 同样没法工作如果你的model里有\nDateTimeField 或者其他特殊的 Field 以及额外数据。\n\ndjango-rest-framework serializers\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\ndjango-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。\n他拥有完善的序列化器，但在使用之前你需要花费一些时间入门, 并学习 cbv\n的开发方式, 对于有时间需求的项目显然这不是最好的解决方案。\n\ndjango simple serializer\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n我希望可以快速简单的序列化数据,\n所以我设计了一种可以不用任何额外的配置与学习而将Django data 或者 python\ndata 序列化为相应的数据的简单的方式。 这就是为什么我写了 django simple\nserializer。\n\ndjango simple serializer 的实际例子: `我的个人网站后台数据接口`_\n\n--------------\n\n运行需求\n--------\n\nPython 2:\n~~~~~~~~~\n\nDjango >= 1.5\n\nPython >= 2.6\n\nPython 3:\n~~~~~~~~~\n\nDjango >= 1.8\n\nPython >= 3\n\n安装\n----\n\nInstall using pip:\n\n::\n\n    pip install django-simple-serializer\n\n使用 django simple serializer 进行开发\n--------------------------------------\n\n序列化Django data\n~~~~~~~~~~~~~~~~~\n\n假设我们有以下Django models：\n\n::\n\n    class Classification(models.Model):\n        c_name = models.CharField(max_length=30, unique=True)\n\n    class Article(models.Model):\n        caption = models.CharField(max_length=50)\n        classification = models.ForeignKey(Classification, related_name='cls_art')\n        content = models.TextField()\n        publish = models.BooleanField(default=False)\n\n使用django simple serializer的简单例子：\n\n::\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list)\n\ndata:\n\n::\n\n    [{'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}]\n\n默认情况下, 序列器会返回一个 list 或者 dict(对于单个model实例),\n你可以设置参数 “output\\_type” 来决定序列器返回 json/raw.\n\n--------------\n\nAPI 手册\n--------\n\ndss.Serializer\n^^^^^^^^^^^^^^\n\n提供序列器\n\n*function* serializer(\\ *data, datetime\\_format=‘timestamp’,\noutput\\_type=‘raw’, include\\_attr=None, exclude\\_attr=None,\nforeign=False, many=False, through=True*)\n\nParameters:\n^^^^^^^^^^^\n\n-  data(\\ *Required*\\ \\|(QuerySet, Page, list, django model\n   object))-待处理数据\n-  datetime\\_format(\\ *Optional*\\ \\|string)-如果包含 datetime 将\n   datetime 转换成相应格式.默认为 “timestamp”（时间戳）\n-  output\\_type(\\ *Optional*\\ \\|string)-serialize type.\n   默认“raw”原始数据，即返回list或dict\n-  include\\_attr(\\ *Optional*\\ \\|(list, tuple))-只序列化 include\\_attr\n   列表里的字段。默认为 None\n-  exclude\\_attr(\\ *Optional*\\ \\|(list, tuple))-不序列化 exclude\\_attr\n   列表里的字段。默认为 None\n-  foreign(\\ *Optional*\\ \\|bool)-是否序列化 ForeignKeyField\n   。include\\_attr 与 exclude\\_attr 对 ForeignKeyField 依旧有效。 默认为\n   False\n-  many(\\ *Optional*\\ \\|bool)-是否序列化 ManyToManyField 。include\\_attr\n   与 exclude\\_attr 对 ManyToManyField 依旧有效 默认为 False\n-  through(\\ *Optional*\\ \\|bool)-是否序列化 ManyToManyField 中 through\n   属性数据 默认为 True\n\n.. _我的个人网站后台数据接口: https://github.com/bluedazzle/django-vue.js-blog/blob/master/api/views.py\n用法:\n^^^^^\n\n**datetime\\_format:**\n\n+--------------+------------------------------------------------------+\n| parameters   | intro                                                |\n+==============+======================================================+\n| string       | 转换 datetime 为字符串。如： “2015-05-10 10:19:22”   |\n+--------------+------------------------------------------------------+\n| timestamp    | 转换 datetime 为时间戳。如： “1432124420.0”          |\n+--------------+------------------------------------------------------+\n\n例子:\n\n::\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, datetime_format='string', output_type='json')\n\ndata:\n\n::\n\n    [\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"first\",\n            \"publish\": true,\n            \"content\": \"first article\",\n            \"caption\": \"first\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:47:36\",\n            \"modify_time\": \"2015-05-23 22:47:36\",\n            \"id\": 31\n        },\n        {\n            \"read_count\": 0,\n            \"sub_caption\": \"second\",\n            \"publish\": false,\n            \"content\": \"second article\",\n            \"caption\": \"second\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:48:19\",\n            \"modify_time\": \"2015-05-23 22:48:19\",\n            \"id\": 32\n        }\n    ]\n\n**output\\_type**\n\n+--------------+----------------------------------------------------+\n| parameters   | intro                                              |\n+==============+====================================================+\n| raw          | 将list或dict中的特殊对象序列化后输出为list或dict   |\n+--------------+----------------------------------------------------+\n| dict         | 同 raw                                             |\n+--------------+----------------------------------------------------+\n| json         | 转换数据为 json                                    |\n+--------------+----------------------------------------------------+\n\n[STRIKEOUT:xml 转换数据为 xml] (暂时去除)\n\n例子:\n\n::\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()[0]\n    data = serializer(article_list, output_type='json')\n\ndata:\n\n::\n\n    {\n            \"read_count\": 0,\n            \"sub_caption\": \"first\",\n            \"publish\": true,\n            \"content\": \"first article\",\n            \"caption\": \"first\",\n            \"comment_count\": 0,\n            \"create_time\": \"2015-05-23 22:47:36\",\n            \"modify_time\": \"2015-05-23 22:47:36\",\n            \"id\": 31\n        }\n\n**include\\_attr**\n\n例子:\n\n::\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', include_attr=('content', 'caption',))\n\ndata:\n\n::\n\n    [\n        {\n            \"content\": \"first article\",\n            \"caption\": \"first\"\n        },\n        {\n            \"content\": \"second article\",\n            \"caption\": \"second\"\n        }\n    ]\n\n**exclude\\_attr**\n\n例子:\n\n::\n\n    from dss.Serializer import serializer\n    article_list = Article.objects.all()\n    data = serializer(article_list, output_type='json', exclude_attr=('content',))\n\ndata:\n\n::\n\n        [\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"first\",\n                \"publish\": true,\n                \"caption\": \"first\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392456,\n                \"modify_time\": 1432392456,\n                \"id\": 31\n            },\n            {\n                \"read_count\": 0,\n                \"sub_caption\": \"second\",\n                \"publish\": false,\n                \"caption\": \"second\",\n                \"comment_count\": 0,\n                \"create_time\": 1432392499,\n                \"modify_time\": 1432392499,\n                \"id\": 32\n            }\n        ]\n\n\n**foreign**"
  },
  {
    "path": "src/__init__.py",
    "content": "__author__ = 'RaPoSpectre'\n"
  },
  {
    "path": "src/dss/Mixin.py",
    "content": "# coding: utf-8\n\nfrom __future__ import unicode_literals\nfrom __future__ import absolute_import\n\nimport sys\nPY2 = True\nif sys.version < '3':\n    from future.builtins import str, int\n    PY2 = False\n\nimport json\nfrom django.core.paginator import EmptyPage\n\nfrom .Serializer import serializer\nfrom .TimeFormatFactory import TimeFormatFactory\n\ntry:\n    from django.http import HttpResponse\nexcept ImportError:\n    raise RuntimeError('django is required in django simple serializer')\n\n\nclass JsonResponseMixin(object):\n    datetime_type = 'string'\n    foreign = False\n    many = False\n    include_attr = []\n    exclude_attr = []\n\n    def time_format(self, time_obj):\n        time_func = TimeFormatFactory.get_time_func(self.datetime_type)\n        return time_func(time_obj)\n\n    def context_serialize(self, context, *args, **kwargs):\n        try:\n            context.pop('view')\n            context.pop('object')\n        except KeyError:\n            pass\n        except AttributeError:\n            pass\n        # if kwargs.get('multi_extend'):\n        #     self.include_attr.extend(kwargs.get('multi_extend'))\n        return serializer(data=context,\n                          datetime_format=self.datetime_type,\n                          output_type='raw',\n                          foreign=self.foreign,\n                          many=self.many,\n                          include_attr=self.include_attr,\n                          exclude_attr=self.exclude_attr,\n                          dict_check=True)\n\n    @staticmethod\n    def json_serializer(context):\n        return json.dumps(context, indent=4)\n\n    def render_to_response(self, context, **response_kwargs):\n        context_dict = self.context_serialize(context)\n        json_context = self.json_serializer(context_dict)\n        return HttpResponse(json_context, content_type='application/json', **response_kwargs)\n\n\nclass FormJsonResponseMixin(JsonResponseMixin):\n    def context_serialize(self, context, *args, **kwargs):\n        form_list = []\n        form = context.get('form', None)\n        if form:\n            for itm in form.fields:\n                f_dict = {'field': str(itm)}\n                form_list.append(f_dict)\n        context_dict = super(FormJsonResponseMixin, self).context_serialize(context, *args, **kwargs)\n        context_dict['form'] = form_list\n        return context_dict\n\n\nclass MultipleJsonResponseMixin(JsonResponseMixin):\n    def context_serialize(self, context, *args, **kwargs):\n        # multi_extend = [i for i in context.keys() if not i.startswith('object') and i.endswith('_list')]\n        # kwargs['multi_extend'] = multi_extend\n        page_dict = {}\n        is_paginated = context.get('is_paginated', None)\n        if is_paginated:\n            page_obj = context['page_obj']\n            page_dict['current'] = page_obj.number\n            page_dict['total'] = page_obj.paginator.num_pages\n            try:\n                previous_page = page_obj.previous_page_number()\n            except EmptyPage:\n                previous_page = None\n            try:\n                next_page = page_obj.next_page_number()\n            except EmptyPage:\n                next_page = None\n            page_dict['previous'] = previous_page\n            page_dict['next'] = next_page\n            page_dict['page_range'] = [{'page': i} for i in page_obj.paginator.page_range]\n        try:\n            context.pop('paginator')\n            context.pop('object_list')\n        except KeyError:\n            pass\n        except AttributeError:\n            pass\n        context_dict = super(MultipleJsonResponseMixin, self).context_serialize(context, *args, **kwargs)\n        context_dict['page_obj'] = page_dict\n        return context_dict\n"
  },
  {
    "path": "src/dss/Serializer.py",
    "content": "# coding: utf-8\nfrom __future__ import unicode_literals\nimport sys\n\nPY2 = True\nif sys.version < '3':\n    from future.builtins import str, int\n    PY2 = False\n\nimport datetime\nimport json\n\nfrom decimal import Decimal\n\nfrom .TimeFormatFactory import TimeFormatFactory\n\ntry:\n    from django.db import models\n    from django.db.models import manager\n    from django.core.paginator import Page\n    from django.db.models.query import QuerySet\n    from django.db.models.fields.files import ImageFieldFile, FileField\nexcept ImportError:\n    raise RuntimeError('django is required in django simple serializer')\n\n\nclass Serializer(object):\n    include_attr = []\n    exclude_attr = []\n    objects = []\n    origin_data = None\n    output_type = 'raw'\n    datetime_format = 'timestamp'\n    foreign = False\n    many = False\n    through = True\n\n    def __init__(self, data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None,\n                 foreign=False, many=False, through=True, *args, **kwargs):\n        if include_attr:\n            self.include_attr = include_attr\n        if exclude_attr:\n            self.exclude_attr = exclude_attr\n        self.origin_data = data\n        self.output_type = output_type\n        self.foreign = foreign\n        self.many = many\n        self.through = through\n        self.through_fields = []\n        self.source_field = None\n        self.datetime_format = datetime_format\n        self.time_func = TimeFormatFactory.get_time_func(datetime_format)\n        self._dict_check = kwargs.get('dict_check', False)\n\n    def check_attr(self, attr):\n        if self.exclude_attr and attr in self.exclude_attr:\n            return False\n        if self.include_attr and attr not in self.include_attr:\n            return False\n        return True\n\n    def data_inspect(self, data, extra=None):\n        if isinstance(data, (QuerySet, Page, list)):\n            convert_data = []\n            if extra:\n                for i, obj in enumerate(data):\n                    convert_data.append(self.data_inspect(obj, extra.get(\n                        **{self.through_fields[0]: obj, self.through_fields[1]: self.source_field})))\n            else:\n                for obj in data:\n                    convert_data.append(self.data_inspect(obj))\n            return convert_data\n        elif isinstance(data, models.Model):\n            obj_dict = {}\n            concrete_model = data._meta.concrete_model\n            for field in concrete_model._meta.local_fields:\n                if field.rel is None:\n                    if self.check_attr(field.name) and hasattr(data, field.name):\n                        obj_dict[field.name] = self.data_inspect(getattr(data, field.name))\n                else:\n                    if self.check_attr(field.name) and self.foreign:\n                        obj_dict[field.name] = self.data_inspect(getattr(data, field.name))\n            for field in concrete_model._meta.many_to_many:\n                if self.check_attr(field.name) and self.many:\n                    obj_dict[field.name] = self.data_inspect(getattr(data, field.name))\n            for k, v in data.__dict__.items():\n                if not str(k).startswith('_') and k not in obj_dict.keys() and self.check_attr(k):\n                    obj_dict[k] = self.data_inspect(v)\n            if extra:\n                for field in extra._meta.concrete_model._meta.local_fields:\n                    if field.name not in obj_dict.keys() and field.name not in self.through_fields:\n                        if field.rel is None:\n                            if self.check_attr(field.name) and hasattr(extra, field.name):\n                                obj_dict[field.name] = self.data_inspect(getattr(extra, field.name))\n                        else:\n                            if self.check_attr(field.name) and self.foreign:\n                                obj_dict[field.name] = self.data_inspect(getattr(extra, field.name))\n            return obj_dict\n        elif isinstance(data, manager.Manager):\n            through_list = data.through._meta.concrete_model._meta.local_fields\n            through_data = data.through._default_manager\n            self.through_fields = [data.target_field.name, data.source_field.name]\n            self.source_field = data.instance\n            if len(through_list) > 3 and self.through:\n                return self.data_inspect(data.all(), through_data)\n            else:\n                return self.data_inspect(data.all())\n        elif isinstance(data, (datetime.datetime, datetime.date, datetime.time)):\n            return self.time_func(data)\n        elif isinstance(data, (ImageFieldFile, FileField)):\n            return data.url if data.url else data.path\n        elif isinstance(data, Decimal):\n            return float(data)\n        elif isinstance(data, dict):\n            obj_dict = {}\n            if self._dict_check:\n                for k, v in data.items():\n                    obj_dict[k] = self.data_inspect(v)\n            else:\n                for k, v in data.items():\n                    if self.check_attr(k):\n                        obj_dict[k] = self.data_inspect(v)\n            return obj_dict\n        elif isinstance(data, (str, bool, float, int)):\n            return data\n        else:\n            return None\n\n    def data_format(self):\n        self.objects = self.data_inspect(self.origin_data)\n\n    def get_values(self):\n        output_switch = {'dict': self.objects,\n                         'raw': self.objects,\n                         'json': json.dumps(self.objects, indent=4)}\n        return output_switch.get(self.output_type, self.objects)\n\n    def __call__(self):\n        self.data_format()\n        return self.get_values()\n\n\ndef serializer(data, datetime_format='timestamp', output_type='raw', include_attr=None, exclude_attr=None,\n               foreign=False, many=False, through=True, *args, **kwargs):\n    s = Serializer(data, datetime_format, output_type, include_attr, exclude_attr,\n                   foreign, many, through, *args, **kwargs)\n    return s()\n"
  },
  {
    "path": "src/dss/TimeFormatFactory.py",
    "content": "# coding: utf-8\n\nimport time\nimport datetime\nfrom functools import partial\n\ntry:\n    from django.utils import timezone\nexcept ImportError:\n    raise RuntimeError('Django is required for django simple serializer.')\n\n\nclass TimeFormatFactory(object):\n    def __init__(self):\n        super(TimeFormatFactory, self).__init__()\n\n    @staticmethod\n    def datetime_to_string(datetime_time, time_format='%Y-%m-%d %H:%M:%S'):\n        if isinstance(datetime_time, datetime.datetime):\n            if datetime_time.tzinfo:\n                datetime_time = datetime_time.astimezone(timezone.get_current_timezone())\n            return datetime_time.strftime(time_format)\n        elif isinstance(datetime_time, datetime.time):\n            time_format = '%H:%M:%S'\n        elif isinstance(datetime_time, datetime.date):\n            time_format = '%Y-%m-%d'\n        return datetime_time.strftime(time_format)\n\n    @staticmethod\n    def datetime_to_timestamp(datetime_time, time_format=None):\n        if isinstance(datetime_time, datetime.datetime):\n            if datetime_time.tzinfo:\n                datetime_time = datetime_time.astimezone(timezone.get_current_timezone())\n            return time.mktime(datetime_time.timetuple())\n        return time.mktime(datetime_time.timetuple())\n\n    @staticmethod\n    def get_time_func(func_type='string'):\n        if func_type == 'string':\n            return TimeFormatFactory.datetime_to_string\n        elif func_type == 'timestamp':\n            return TimeFormatFactory.datetime_to_timestamp\n        else:\n            return TimeFormatFactory.datetime_to_string\n"
  },
  {
    "path": "src/dss/Warning.py",
    "content": "from __future__ import unicode_literals\nimport warnings\n\n\nclass RemovedInNextVersionWarning(DeprecationWarning):\n    pass\n\n\ndef remove_check(**kwargs):\n    deep = kwargs.get('deep', None)\n    if deep is not None:\n        warnings.warn('Parameter \"deep\" will removed in next version!', RemovedInNextVersionWarning, stacklevel=2)\n        return deep\n    return None\n"
  },
  {
    "path": "src/dss/__init__.py",
    "content": "__author__ = 'RaPoSpectre'\n"
  },
  {
    "path": "src/setup.py",
    "content": "import codecs\nimport os\nimport sys\n\ntry:\n    from setuptools import setup\nexcept ImportError:\n    from distutils.core import setup\n\n\ndef read(fname):\n    return codecs.open(os.path.join(os.path.dirname(__file__), fname)).read()\n\n\nNAME = \"django-simple-serializer\"\n\nPACKAGES = [\"dss\", ]\n\nDESCRIPTION = \"Django Simple Serializer is a serializer to help user serialize django data or python list into json,xml,dict data in a simple way.\"\n\nLONG_DESCRIPTION = read(\"README.rst\")\n\nKEYWORDS = \"django serializer\"\n\nAUTHOR = \"RaPoSpectre\"\n\nAUTHOR_EMAIL = \"rapospectre@gmail.com\"\n\nURL = \"https://github.com/bluedazzle/django-simple-serializer\"\n\nVERSION = \"2.0.7\"\n\nLICENSE = \"MIT\"\n\nsetup(\n    name=NAME,\n    version=VERSION,\n    description=DESCRIPTION,\n    long_description=LONG_DESCRIPTION,\n    classifiers=[\n        'License :: OSI Approved :: MIT License',\n        'Programming Language :: Python',\n        'Intended Audience :: Developers',\n        'Operating System :: OS Independent',\n    ],\n    install_requires=[\n        'future'\n    ],\n\n    keywords=KEYWORDS,\n    author=AUTHOR,\n    author_email=AUTHOR_EMAIL,\n    url=URL,\n    license=LICENSE,\n    packages=PACKAGES,\n    include_package_data=True,\n    zip_safe=True,\n)\n"
  },
  {
    "path": "src/test/__init__.py",
    "content": "__author__ = 'RaPoSpectre'\n"
  },
  {
    "path": "src/test/test_Mixin.py",
    "content": "# coding: utf-8\nfrom __future__ import unicode_literals\nfrom __future__ import absolute_import\nimport json\n\nfrom unittest import TestCase\nfrom ..dss.Mixin import JsonResponseMixin, FormJsonResponseMixin, MultipleJsonResponseMixin\n\nimport datetime\n\n\nclass TestJsonResponseMixin(TestCase):\n    def setUp(self):\n        self.json_mixin = JsonResponseMixin()\n        self.json_mixin.datetime_type = 'string'\n\n    def test_time_format(self):\n        res = self.json_mixin.time_format(datetime.datetime(2015, 12, 12, 12))\n        self.assertEqual(res, '2015-12-12 12:00:00')\n\n    def test_render_to_response(self):\n        context = {'title': 'test', 'name': 'test_name'}\n        resp = self.json_mixin.render_to_response(context=context)\n        self.assertEqual(resp.content, json.dumps(context, indent=4))\n\n\nclass TestFormJsonResponseMixin(TestCase):\n    def setUp(self):\n        self.form_mixin = FormJsonResponseMixin()\n        self.form_mixin.datetime_type = 'string'\n\n        class TestForm(object):\n            fields = ['form1', 'form2', 'form3']\n        self.form = TestForm()\n\n    def test_context_serialize(self):\n        context = {'title': 'test_title',\n                   'form': self.form}\n        result = self.form_mixin.context_serialize(context)\n        expect_res = {'title': 'test_title',\n                      'form': [{'field': 'form1'},\n                               {'field': 'form2'},\n                               {'field': 'form3'}]}\n        self.assertEqual(result, expect_res)\n\n\nclass TestMultipleJsonResponseMixin(TestCase):\n    def setUp(self):\n        self.multi_mixin = MultipleJsonResponseMixin()\n\n        class TestPaginator(object):\n            pass\n\n        class TestPage(object):\n            number = 1\n            paginator = TestPaginator()\n            setattr(paginator, 'num_pages', 3)\n            setattr(paginator, 'page_range', [1, 2, 3])\n\n            def previous_page_number(self):\n                return None\n\n            def next_page_number(self):\n                return 2\n\n        self.page_obj = TestPage()\n\n    def test_context_serialize(self):\n        context = {'page_obj': self.page_obj,\n                   'is_paginated': True,\n                   'title': 'test'}\n        result = self.multi_mixin.context_serialize(context)\n        expect_res = {'current': 1,\n                      'total': 3,\n                      'previous': None,\n                      'next': 2,\n                      'page_range': [{'page': 1},\n                                     {'page': 2},\n                                     {'page': 3}]}\n        self.assertEqual(result['page_obj'], expect_res)"
  },
  {
    "path": "src/test/test_Serializer.py",
    "content": "# coding: utf-8\nfrom __future__ import unicode_literals\nimport json\n\nfrom unittest import TestCase\nimport datetime\nfrom django.db import models\nfrom django.conf import settings\nfrom dss.TimeFormatFactory import TimeFormatFactory\nfrom dss.Serializer import serializer\n\n__author__ = 'RaPoSpectre'\n\n\nclass Test_Serializer(TestCase):\n    def setUp(self):\n        self.time_func = TimeFormatFactory.get_time_func('string')\n        # DATABASES = {\n        #     'default': {\n        #     'ENGINE': 'django.db.backends.sqlite3',\n        #     'NAME': ':memory:',\n        #     'USER': '',                      # Not used with sqlite3.\n        #     'PASSWORD': '',                  # Not used with sqlite3.\n        #     'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.\n        #     'PORT': '',\n        #     }\n        # }\n        # settings.configure(DATABASES=DATABASES, DEBUG=True)\n        # class TestAuthor(models.Model):\n        #     name = models.CharField(default='test_author')\n        #\n        #     def __unicode__(self):\n        #         return self.name\n        #\n        # class TestTags(models.Model):\n        #     tag = models.CharField(default='test_tag')\n        #     create_time = models.DateTimeField(auto_now=True)\n        #\n        # class TestArticle(models.Model):\n        #     title = models.CharField(default='test')\n        #     content = models.CharField(default='test')\n        #     author = models.ForeignKey(TestAuthor, related_name='author_art')\n        #     tags = models.ManyToManyField(TestTags, related_name='tag_art')\n        #     create_time = models.DateTimeField(auto_now=True)\n        #\n        #\n        # self.author = TestAuthor()\n        # self.author.save()\n        # tags = TestTags(tag='tag1')\n        # tags.save()\n        # self.article = TestArticle(author=self.author)\n        # self.article.tags.add(tags)\n        # self.article.save()\n\n    def test_serializer(self):\n        test_data = {'title': 'test',\n                     'name': 'attr',\n                     'time': datetime.datetime(2015, 10, 10, 12),\n                     'list': [{'content': 'list_content',\n                               'time': datetime.datetime(2015, 10, 11, 9)},\n                              {'content': 'list_content1',\n                               'time': datetime.datetime(2015, 12, 22, 9)}]}\n        result = serializer(test_data, datetime_format='string', output_type='raw')\n        self.assertEqual(result['time'], '2015-10-10 12:00:00')\n        self.assertIsInstance(result, dict)\n        self.assertEqual(result['list'][0]['time'], '2015-10-11 09:00:00')\n        result = serializer(test_data, datetime_format='timestamp', output_type='json')\n        self.assertEqual(json.loads(result)['title'], 'test')\n        self.assertEqual(json.loads(result)['list'][0]['content'], 'list_content')\n"
  },
  {
    "path": "src/test/test_TimeFormatFactory.py",
    "content": "import unittest\nimport datetime\n\nfrom ..dss.TimeFormatFactory import TimeFormatFactory\n\n\nclass TestTimeFormatFactory(unittest.TestCase):\n    def setUp(self):\n        self.time_factory = TimeFormatFactory()\n\n    def test_create_string(self):\n        new_time = datetime.datetime(2015, 5, 20, 20, 20, 20)\n        time_func = self.time_factory.get_time_func('string')\n        time_str = time_func(new_time)\n        self.assertEqual(time_str, '2015-05-20 20:20:20')\n\n    def test_create_timestamp(self):\n        new_time = datetime.datetime(2015, 5, 20, 20, 20, 20)\n        time_func = self.time_factory.get_time_func('timestamp')\n        time_stamp = time_func(new_time)\n        self.assertEqual(time_stamp, 1432124420.0)\n\n    def test_get_time_func(self):\n        time_func = self.time_factory.get_time_func('string')\n        time_str = time_func(datetime.datetime(1999, 9, 9, 9))\n        self.assertEqual(time_str, '1999-09-09 09:00:00')\n\nif __name__ == '__main__':\n    unittest.main()\n"
  }
]