├── .editorconfig ├── .gitignore ├── .python-version ├── .travis.yml ├── AUTHORS.rst ├── CONTRIBUTING.rst ├── HISTORY.rst ├── LICENSE ├── MANIFEST.in ├── Makefile ├── Pipfile ├── Pipfile.lock ├── README.md ├── prettyjson ├── __init__.py ├── models.py ├── static │ └── prettyjson │ │ ├── prettyjson.css │ │ └── prettyjson.js ├── templates │ └── prettyjson │ │ └── base.html ├── templatetags │ ├── __init__.py │ └── prettyjson.py └── widgets.py ├── requirements-test.txt ├── requirements.txt ├── requirements_dev.txt ├── runtests.py ├── setup.cfg ├── setup.py ├── tests ├── __init__.py ├── test_models.py └── test_prettyjson.py └── tox.ini /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.{py,rst,ini}] 12 | indent_style = space 13 | indent_size = 4 14 | 15 | [*.{html,css,scss,json,yml}] 16 | indent_style = space 17 | indent_size = 2 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | 22 | [Makefile] 23 | indent_style = tab 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | __pycache__ 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | var 16 | sdist 17 | develop-eggs 18 | .installed.cfg 19 | lib 20 | lib64 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | htmlcov 30 | 31 | # Translations 32 | *.mo 33 | 34 | # Mr Developer 35 | .mr.developer.cfg 36 | .project 37 | .pydevproject 38 | 39 | # Pycharm/Intellij 40 | .idea 41 | 42 | # Complexity 43 | output/*.html 44 | output/*/index.html 45 | 46 | # Sphinx 47 | docs/_build 48 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | system 2 | 3.3.6 3 | 3.4.4 4 | 3.5.1 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Config file for automatic testing at travis-ci.org 2 | 3 | language: python 4 | 5 | python: 6 | - "2.7" 7 | - "3.3" 8 | - "3.4" 9 | - "3.5" 10 | 11 | 12 | env: 13 | matrix: 14 | - DJANGO="Django<1.9" 15 | - DJANGO="Django<1.10" 16 | 17 | cache: pip 18 | 19 | matrix: 20 | exclude: 21 | - python: "3.3" 22 | env: DJANGO="Django<1.10" 23 | # Django 1.9+ does not support python 3.3 24 | 25 | 26 | before_install: 27 | - pip install codecov 28 | 29 | # command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors 30 | install: 31 | - pip install "$DJANGO" 32 | - pip install -r requirements-test.txt 33 | 34 | # command to run tests using coverage, e.g. python setup.py test 35 | script: coverage run --source prettyjson runtests.py 36 | 37 | after_success: 38 | - codecov 39 | -------------------------------------------------------------------------------- /AUTHORS.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | Credits 3 | ======= 4 | 5 | Development Lead 6 | ---------------- 7 | 8 | * Kevin Mickey 9 | 10 | Contributors 11 | ------------ 12 | 13 | None yet. Why not be the first? 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | Contributing 3 | ============ 4 | 5 | Contributions are welcome, and they are greatly appreciated! Every 6 | little bit helps, and credit will always be given. 7 | 8 | You can contribute in many ways: 9 | 10 | Types of Contributions 11 | ---------------------- 12 | 13 | Report Bugs 14 | ~~~~~~~~~~~ 15 | 16 | Report bugs at https://github.com/kevinmickey/django-prettyjson/issues. 17 | 18 | If you are reporting a bug, please include: 19 | 20 | * Your operating system name and version. 21 | * Any details about your local setup that might be helpful in troubleshooting. 22 | * Detailed steps to reproduce the bug. 23 | 24 | Fix Bugs 25 | ~~~~~~~~ 26 | 27 | Look through the GitHub issues for bugs. Anything tagged with "bug" 28 | is open to whoever wants to implement it. 29 | 30 | Implement Features 31 | ~~~~~~~~~~~~~~~~~~ 32 | 33 | Look through the GitHub issues for features. Anything tagged with "feature" 34 | is open to whoever wants to implement it. 35 | 36 | Write Documentation 37 | ~~~~~~~~~~~~~~~~~~~ 38 | 39 | django-prettyjson could always use more documentation, whether as part of the 40 | official django-prettyjson docs, in docstrings, or even on the web in blog posts, 41 | articles, and such. 42 | 43 | Submit Feedback 44 | ~~~~~~~~~~~~~~~ 45 | 46 | The best way to send feedback is to file an issue at https://github.com/kevinmickey/django-prettyjson/issues. 47 | 48 | If you are proposing a feature: 49 | 50 | * Explain in detail how it would work. 51 | * Keep the scope as narrow as possible, to make it easier to implement. 52 | * Remember that this is a volunteer-driven project, and that contributions 53 | are welcome :) 54 | 55 | Get Started! 56 | ------------ 57 | 58 | Ready to contribute? Here's how to set up `django-prettyjson` for local development. 59 | 60 | 1. Fork the `django-prettyjson` repo on GitHub. 61 | 2. Clone your fork locally:: 62 | 63 | $ git clone git@github.com:your_name_here/django-prettyjson.git 64 | 65 | 3. Install your local copy into a virtualenv. Assuming you have virtualenvwrapper installed, this is how you set up your fork for local development:: 66 | 67 | $ mkvirtualenv django-prettyjson 68 | $ cd django-prettyjson/ 69 | $ python setup.py develop 70 | 71 | 4. Create a branch for local development:: 72 | 73 | $ git checkout -b name-of-your-bugfix-or-feature 74 | 75 | Now you can make your changes locally. 76 | 77 | 5. When you're done making changes, check that your changes pass flake8 and the 78 | tests, including testing other Python versions with tox:: 79 | 80 | $ flake8 prettyjson tests 81 | $ python setup.py test 82 | $ tox 83 | 84 | To get flake8 and tox, just pip install them into your virtualenv. 85 | 86 | 6. Commit your changes and push your branch to GitHub:: 87 | 88 | $ git add . 89 | $ git commit -m "Your detailed description of your changes." 90 | $ git push origin name-of-your-bugfix-or-feature 91 | 92 | 7. Submit a pull request through the GitHub website. 93 | 94 | Pull Request Guidelines 95 | ----------------------- 96 | 97 | Before you submit a pull request, check that it meets these guidelines: 98 | 99 | 1. The pull request should include tests. 100 | 2. If the pull request adds functionality, the docs should be updated. Put 101 | your new functionality into a function with a docstring, and add the 102 | feature to the list in README.rst. 103 | 3. The pull request should work for Python 2.7, 3.3, 3.4, and 3.5. Check 104 | https://travis-ci.org/kevinmickey/django-prettyjson/pull_requests 105 | and make sure that the tests pass for all supported Python versions. 106 | 107 | Tips 108 | ---- 109 | 110 | To run a subset of tests:: 111 | 112 | $ python -m unittest tests.test_prettyjson 113 | 114 | Publishing 115 | ---------- 116 | 117 | 1. Update changelog and commit to git (or stage and use --allow-dirty in bumpversion) 118 | 2. `pipenv run bumpversion [major,minor,patch]` - Bump version, commit to git, and add tag 119 | 3. `git push origin` and `git push origin --tags` 120 | 4. `pipenv run make release` - cleans and publishes to pypi 121 | -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | .. :changelog: 2 | 3 | History 4 | ------- 5 | 6 | 0.1.0 (2016-05-28) 7 | ++++++++++++++++++ 8 | 9 | * First release. 10 | 11 | 0.2.0 (2016-05-29) 12 | ++++++++++++++++++ 13 | 14 | * Switched to using standardjson for encoding objects 15 | * Added setup option for those with jquery already loaded 16 | 17 | 0.2.1 (2016-07-01) 18 | ++++++++++++++++++ 19 | 20 | * Fixed manifest 21 | 22 | 0.2.2 (2016-12-07) 23 | ++++++++++++++++++ 24 | 25 | * Added dependencies to setup.py 26 | 27 | 0.3.0 (2017-05-23) 28 | ++++++++++++++++++ 29 | 30 | * Added "initial" option to show raw or parsed initial 31 | * Requires six 32 | 33 | 0.3.1 (2018-04-01) 34 | ++++++++++++++++++ 35 | 36 | * Allows CSS control of parsed widget 37 | 38 | 0.3.2 (2018-04-09) 39 | ++++++++++++++++++ 40 | 41 | * Fixes widget media order 42 | 43 | 0.3.3 (2018-04-13) 44 | ++++++++++++++++++ 45 | 46 | * Fixes string passed as parameter 47 | 48 | 0.4.0 (2018-04-30) 49 | ++++++++++++++++++ 50 | 51 | * Allows attrs in template tag 52 | * Fix JS for initial parsed with multiple widgets 53 | * Change parsed CSS height to max-height 54 | 55 | 0.4.1 (2018-08-07) 56 | ++++++++++++++++++ 57 | 58 | * Fix widget for Django 2.1 59 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Kevin Mickey 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | * 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. 9 | 10 | * Neither the name of django-prettyjson nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | 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. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS.rst 2 | include CONTRIBUTING.rst 3 | include HISTORY.rst 4 | include LICENSE 5 | include README.md 6 | recursive-include prettyjson *.html *.png *.gif *js *.css *jpg *jpeg *svg *py 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: clean-pyc clean-build docs help 2 | .DEFAULT_GOAL := help 3 | define BROWSER_PYSCRIPT 4 | import os, webbrowser, sys 5 | try: 6 | from urllib import pathname2url 7 | except: 8 | from urllib.request import pathname2url 9 | 10 | webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1]))) 11 | endef 12 | export BROWSER_PYSCRIPT 13 | BROWSER := python -c "$$BROWSER_PYSCRIPT" 14 | 15 | help: 16 | @perl -nle'print $& if m{^[a-zA-Z_-]+:.*?## .*$$}' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}' 17 | 18 | clean: clean-build clean-pyc 19 | 20 | clean-build: ## remove build artifacts 21 | rm -fr build/ 22 | rm -fr dist/ 23 | rm -fr *.egg-info 24 | 25 | clean-pyc: ## remove Python file artifacts 26 | find . -name '*.pyc' -exec rm -f {} + 27 | find . -name '*.pyo' -exec rm -f {} + 28 | find . -name '*~' -exec rm -f {} + 29 | 30 | lint: ## check style with flake8 31 | flake8 prettyjson tests 32 | 33 | test: ## run tests quickly with the default Python 34 | python runtests.py tests 35 | 36 | test-all: ## run tests on every Python version with tox 37 | tox 38 | 39 | coverage: ## check code coverage quickly with the default Python 40 | coverage run --source prettyjson runtests.py tests 41 | coverage report -m 42 | coverage html 43 | open htmlcov/index.html 44 | 45 | docs: ## generate Sphinx HTML documentation, including API docs 46 | rm -f docs/django-prettyjson.rst 47 | rm -f docs/modules.rst 48 | sphinx-apidoc -o docs/ prettyjson 49 | $(MAKE) -C docs clean 50 | $(MAKE) -C docs html 51 | $(BROWSER) docs/_build/html/index.html 52 | 53 | release: clean ## package and upload a release 54 | python setup.py sdist upload 55 | python setup.py bdist_wheel upload 56 | 57 | sdist: clean ## package 58 | python setup.py sdist 59 | ls -l dist 60 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | url = "https://pypi.python.org/simple" 3 | verify_ssl = true 4 | name = "pypi" 5 | 6 | [packages] 7 | Django = ">=1.8" 8 | standardjson = ">=0.3.1" 9 | six = ">=1.10.0" 10 | 11 | [dev-packages] 12 | bumpversion = "*" 13 | wheel = "*" 14 | coverage = "*" 15 | mock = ">=1.0.1" 16 | "flake8" = ">=2.1.0" 17 | tox = ">=1.7.0" 18 | 19 | [requires] 20 | python_version = "3.6" 21 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "093d340404fcb020ddc89e90ff4fb33d5cf29beb452621e6d240d0d09727b3e4" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.6" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.python.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "django": { 20 | "hashes": [ 21 | "sha256:7f246078d5a546f63c28fc03ce71f4d7a23677ce42109219c24c9ffb28416137", 22 | "sha256:ea50d85709708621d956187c6b61d9f9ce155007b496dd914fdb35db8d790aec" 23 | ], 24 | "index": "pypi", 25 | "version": "==2.1" 26 | }, 27 | "pytz": { 28 | "hashes": [ 29 | "sha256:a061aa0a9e06881eb8b3b2b43f05b9439d6583c206d0a6c340ff72a7b6669053", 30 | "sha256:ffb9ef1de172603304d9d2819af6f5ece76f2e85ec10692a524dd876e72bf277" 31 | ], 32 | "version": "==2018.5" 33 | }, 34 | "six": { 35 | "hashes": [ 36 | "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", 37 | "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" 38 | ], 39 | "index": "pypi", 40 | "version": "==1.11.0" 41 | }, 42 | "standardjson": { 43 | "hashes": [ 44 | "sha256:69e79b090d3f7dd887ae4a9db226ea79cd3fd3d7cfa8491d23ec6b06126e24b0", 45 | "sha256:71b7b0a649d5e3bd343a02737e752c054c218242dcaa739abab98086e537fbab" 46 | ], 47 | "index": "pypi", 48 | "version": "==0.3.1" 49 | } 50 | }, 51 | "develop": { 52 | "bumpversion": { 53 | "hashes": [ 54 | "sha256:6744c873dd7aafc24453d8b6a1a0d6d109faf63cd0cd19cb78fd46e74932c77e", 55 | "sha256:6753d9ff3552013e2130f7bc03c1007e24473b4835952679653fb132367bdd57" 56 | ], 57 | "index": "pypi", 58 | "version": "==0.5.3" 59 | }, 60 | "coverage": { 61 | "hashes": [ 62 | "sha256:03481e81d558d30d230bc12999e3edffe392d244349a90f4ef9b88425fac74ba", 63 | "sha256:0b136648de27201056c1869a6c0d4e23f464750fd9a9ba9750b8336a244429ed", 64 | "sha256:10a46017fef60e16694a30627319f38a2b9b52e90182dddb6e37dcdab0f4bf95", 65 | "sha256:198626739a79b09fa0a2f06e083ffd12eb55449b5f8bfdbeed1df4910b2ca640", 66 | "sha256:23d341cdd4a0371820eb2b0bd6b88f5003a7438bbedb33688cd33b8eae59affd", 67 | "sha256:28b2191e7283f4f3568962e373b47ef7f0392993bb6660d079c62bd50fe9d162", 68 | "sha256:2a5b73210bad5279ddb558d9a2bfedc7f4bf6ad7f3c988641d83c40293deaec1", 69 | "sha256:2eb564bbf7816a9d68dd3369a510be3327f1c618d2357fa6b1216994c2e3d508", 70 | "sha256:337ded681dd2ef9ca04ef5d93cfc87e52e09db2594c296b4a0a3662cb1b41249", 71 | "sha256:3a2184c6d797a125dca8367878d3b9a178b6fdd05fdc2d35d758c3006a1cd694", 72 | "sha256:3c79a6f7b95751cdebcd9037e4d06f8d5a9b60e4ed0cd231342aa8ad7124882a", 73 | "sha256:3d72c20bd105022d29b14a7d628462ebdc61de2f303322c0212a054352f3b287", 74 | "sha256:3eb42bf89a6be7deb64116dd1cc4b08171734d721e7a7e57ad64cc4ef29ed2f1", 75 | "sha256:4635a184d0bbe537aa185a34193898eee409332a8ccb27eea36f262566585000", 76 | "sha256:56e448f051a201c5ebbaa86a5efd0ca90d327204d8b059ab25ad0f35fbfd79f1", 77 | "sha256:5a13ea7911ff5e1796b6d5e4fbbf6952381a611209b736d48e675c2756f3f74e", 78 | "sha256:69bf008a06b76619d3c3f3b1983f5145c75a305a0fea513aca094cae5c40a8f5", 79 | "sha256:6bc583dc18d5979dc0f6cec26a8603129de0304d5ae1f17e57a12834e7235062", 80 | "sha256:701cd6093d63e6b8ad7009d8a92425428bc4d6e7ab8d75efbb665c806c1d79ba", 81 | "sha256:7608a3dd5d73cb06c531b8925e0ef8d3de31fed2544a7de6c63960a1e73ea4bc", 82 | "sha256:76ecd006d1d8f739430ec50cc872889af1f9c1b6b8f48e29941814b09b0fd3cc", 83 | "sha256:7aa36d2b844a3e4a4b356708d79fd2c260281a7390d678a10b91ca595ddc9e99", 84 | "sha256:7d3f553904b0c5c016d1dad058a7554c7ac4c91a789fca496e7d8347ad040653", 85 | "sha256:7e1fe19bd6dce69d9fd159d8e4a80a8f52101380d5d3a4d374b6d3eae0e5de9c", 86 | "sha256:8c3cb8c35ec4d9506979b4cf90ee9918bc2e49f84189d9bf5c36c0c1119c6558", 87 | "sha256:9d6dd10d49e01571bf6e147d3b505141ffc093a06756c60b053a859cb2128b1f", 88 | "sha256:be6cfcd8053d13f5f5eeb284aa8a814220c3da1b0078fa859011c7fffd86dab9", 89 | "sha256:c1bb572fab8208c400adaf06a8133ac0712179a334c09224fb11393e920abcdd", 90 | "sha256:de4418dadaa1c01d497e539210cb6baa015965526ff5afc078c57ca69160108d", 91 | "sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6", 92 | "sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80" 93 | ], 94 | "index": "pypi", 95 | "version": "==4.5.1" 96 | }, 97 | "flake8": { 98 | "hashes": [ 99 | "sha256:7253265f7abd8b313e3892944044a365e3f4ac3fcdcfb4298f55ee9ddf188ba0", 100 | "sha256:c7841163e2b576d435799169b78703ad6ac1bbb0f199994fc05f700b2a90ea37" 101 | ], 102 | "index": "pypi", 103 | "version": "==3.5.0" 104 | }, 105 | "mccabe": { 106 | "hashes": [ 107 | "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", 108 | "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" 109 | ], 110 | "version": "==0.6.1" 111 | }, 112 | "mock": { 113 | "hashes": [ 114 | "sha256:5ce3c71c5545b472da17b72268978914d0252980348636840bd34a00b5cc96c1", 115 | "sha256:b158b6df76edd239b8208d481dc46b6afd45a846b7812ff0ce58971cf5bc8bba" 116 | ], 117 | "index": "pypi", 118 | "version": "==2.0.0" 119 | }, 120 | "packaging": { 121 | "hashes": [ 122 | "sha256:e9215d2d2535d3ae866c3d6efc77d5b24a0192cce0ff20e42896cc0664f889c0", 123 | "sha256:f019b770dd64e585a99714f1fd5e01c7a8f11b45635aa953fd41c689a657375b" 124 | ], 125 | "version": "==17.1" 126 | }, 127 | "pbr": { 128 | "hashes": [ 129 | "sha256:1b8be50d938c9bb75d0eaf7eda111eec1bf6dc88a62a6412e33bf077457e0f45", 130 | "sha256:b486975c0cafb6beeb50ca0e17ba047647f229087bd74e37f4a7e2cac17d2caa" 131 | ], 132 | "version": "==4.2.0" 133 | }, 134 | "pluggy": { 135 | "hashes": [ 136 | "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", 137 | "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" 138 | ], 139 | "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*'", 140 | "version": "==0.7.1" 141 | }, 142 | "py": { 143 | "hashes": [ 144 | "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", 145 | "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" 146 | ], 147 | "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.3.*'", 148 | "version": "==1.5.4" 149 | }, 150 | "pycodestyle": { 151 | "hashes": [ 152 | "sha256:682256a5b318149ca0d2a9185d365d8864a768a28db66a84a2ea946bcc426766", 153 | "sha256:6c4245ade1edfad79c3446fadfc96b0de2759662dc29d07d80a6f27ad1ca6ba9" 154 | ], 155 | "version": "==2.3.1" 156 | }, 157 | "pyflakes": { 158 | "hashes": [ 159 | "sha256:08bd6a50edf8cffa9fa09a463063c425ecaaf10d1eb0335a7e8b1401aef89e6f", 160 | "sha256:8d616a382f243dbf19b54743f280b80198be0bca3a5396f1d2e1fca6223e8805" 161 | ], 162 | "version": "==1.6.0" 163 | }, 164 | "pyparsing": { 165 | "hashes": [ 166 | "sha256:0832bcf47acd283788593e7a0f542407bd9550a55a8a8435214a1960e04bcb04", 167 | "sha256:fee43f17a9c4087e7ed1605bd6df994c6173c1e977d7ade7b651292fab2bd010" 168 | ], 169 | "version": "==2.2.0" 170 | }, 171 | "six": { 172 | "hashes": [ 173 | "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", 174 | "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" 175 | ], 176 | "index": "pypi", 177 | "version": "==1.11.0" 178 | }, 179 | "tox": { 180 | "hashes": [ 181 | "sha256:0a0f1e8e15569e6507597517aa9e890434e8cc604bf229748c877751b4498054", 182 | "sha256:0b3efa8fb125c65e531619920ec904862f8b6c04a15f929ada3949e12973dbc8" 183 | ], 184 | "index": "pypi", 185 | "version": "==3.1.3" 186 | }, 187 | "virtualenv": { 188 | "hashes": [ 189 | "sha256:2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669", 190 | "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752" 191 | ], 192 | "markers": "python_version != '3.2.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*'", 193 | "version": "==16.0.0" 194 | }, 195 | "wheel": { 196 | "hashes": [ 197 | "sha256:0a2e54558a0628f2145d2fc822137e322412115173e8a2ddbe1c9024338ae83c", 198 | "sha256:80044e51ec5bbf6c894ba0bc48d26a8c20a9ba629f4ca19ea26ecfcf87685f5f" 199 | ], 200 | "index": "pypi", 201 | "version": "==0.31.1" 202 | } 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # django-prettyjson 2 | 3 | [![PyPi Version](https://badge.fury.io/py/django-prettyjson.png)](https://badge.fury.io/py/django-prettyjson) [![Build Status](https://travis-ci.org/kevinmickey/django-prettyjson.svg?branch=master)](https://travis-ci.org/kevinmickey/django-prettyjson) 4 | 5 | Enables pretty JSON viewer in Django forms, admin, or templates. The viewer is adapted from [jQuery JSONView](https://github.com/yesmeck/jquery-jsonview). It is compatible with almost anything: JSON stored in a string, a jsonfield (using django.contrib.postgres or [django-jsonfield](https://github.com/bradjasper/django-jsonfield/)), or any python object that can be serialized to JSON (using [standardjson](https://github.com/audreyr/standardjson)). 6 | 7 | ## Demo 8 | 9 | See http://kevinmickey.github.io/django-prettyjson 10 | 11 | ## Installation 12 | 13 | At the command line: 14 | 15 | ```sh 16 | pip install django-prettyjson 17 | ``` 18 | 19 | ## Configuration 20 | 21 | Add `'prettyjson'` to `INSTALLED_APPS` in `settings.py`: 22 | 23 | ```python 24 | INSTALLED_APPS = ( 25 | ..., 26 | 'prettyjson', 27 | ) 28 | ``` 29 | 30 | ## Usage 31 | 32 | In a form or admin of a model, enable a pretty JSON viewer for a particular field: 33 | 34 | ```python 35 | from prettyjson import PrettyJSONWidget 36 | 37 | class JsonForm(forms.ModelForm): 38 | class Meta: 39 | model = Test 40 | fields = '__all__' 41 | widgets = { 42 | 'myjsonfield': PrettyJSONWidget(), 43 | } 44 | 45 | class JsonAdmin(admin.ModelAdmin): 46 | form = JsonForm 47 | ``` 48 | 49 | Enable pretty JSON viewer for every JSONField of a model: 50 | 51 | ```python 52 | from django.contrib.postgres.fields import JSONField 53 | 54 | class JsonAdmin(admin.ModelAdmin): 55 | formfield_overrides = { 56 | JSONField: {'widget': PrettyJSONWidget } 57 | } 58 | ``` 59 | 60 | In templates, you can also enable a pretty JSON viewer. Use the `prettyjson` template tag with a string JSON or with objects (dicts, QuerySets, etc.) that can be serialized to a JSON. Note that the template tag must be loaded using `{% load prettyjson %}`. It also has CSS and JS that must be included using `{% prettyjson_setup %}`. 61 | 62 | ```htmldjango 63 | {% extends "base.html" %} 64 | 65 | {% load prettyjson %} 66 | 67 | {% block header %} 68 | {{ block.super }} 69 | {% prettyjson_setup %} 70 | {% endblock %} 71 | 72 | {% block content %} 73 | {% prettyjson myqueryset %} 74 | {% prettyjson mydict %} 75 | {% prettyjson '{"hey": "guy","anumber": 243,"anobject": {"whoa": "nuts","anarray": [1,2,"thr

ee"], "more":"stuff"},"awesome": true,"bogus": false,"meaning": null, "japanese":"明日がある。", "link": "http://jsonview.com", "notLink": "http://jsonview.com is great"}' %} 76 | {% prettyjson '{}' %} 77 | {% endblock %} 78 | ``` 79 | 80 | The setup includes jQuery, loaded as django.jQuery to avoid namespace conflict. If your page already includes jQuery, use `{% prettyjson_setup jquery=False %}` to avoid loading jQuery a second time. 81 | 82 | ### Configure Rendering 83 | 84 | By default the jsonwidget will render as a raw string with a button to click to change it to parsed json. For it to render as parsed json initially, you can pass an argument: 85 | 86 | ```python 87 | class JsonAdmin(admin.ModelAdmin): 88 | formfield_overrides = { 89 | JSONField: {'widget': PrettyJSONWidget(attrs={'initial': 'parsed'})} 90 | } 91 | ``` 92 | 93 | Or, in a template tag: 94 | 95 | ```python 96 | {% prettyjson mydict initial='parsed' %} 97 | ``` 98 | 99 | ## Running Tests 100 | 101 | In development. 102 | 103 | ```sh 104 | source /bin/activate 105 | (myenv) $ pip install -r requirements-test.txt 106 | (myenv) $ python runtests.py 107 | ``` 108 | 109 | ## Credits 110 | 111 | Dependencies, parts of code, and/or sources of inspiration: 112 | 113 | * [jQuery JSONView](https://github.com/yesmeck/jquery-jsonview) 114 | * [standardjson](https://github.com/audreyr/standardjson) 115 | 116 | Tools used in developing, testing, and/or rendering this package: 117 | 118 | * [Cookiecutter](https://github.com/audreyr/cookiecutter) 119 | * [cookiecutter-djangopackage](https://github.com/pydanny/cookiecutter-djangopackage) 120 | -------------------------------------------------------------------------------- /prettyjson/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '0.4.1' 2 | 3 | from .widgets import PrettyJSONWidget 4 | -------------------------------------------------------------------------------- /prettyjson/models.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | -------------------------------------------------------------------------------- /prettyjson/static/prettyjson/prettyjson.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.jsonview{font-family:monospace;font-size:1.1em;white-space:pre-wrap}.jsonview .prop{font-weight:700}.jsonview .null{color:red}.jsonview .bool,.jsonview .num{color:#00f}.jsonview .string{color:green;white-space:pre-wrap}.jsonview .string.multiline{display:inline-block;vertical-align:text-top}.jsonview .collapser{position:absolute;left:-1em;cursor:pointer}.jsonview .collapsible{transition:height 1.2s;transition:width 1.2s}.jsonview .collapsible.collapsed{height:.8em;width:1em;display:inline-block;overflow:hidden;margin:0}.jsonview .collapsible.collapsed:before{content:"…";width:1em;margin-left:.2em}.jsonview .collapser.collapsed{transform:rotate(0)}.jsonview .q{display:inline-block;width:0;color:transparent}.jsonview li{position:relative}.jsonview ul{list-style:none;margin:0 0 0 2em;padding:0}.jsonview h1{font-size:1.2em} 2 | 3 | form .jsonview ul { 4 | margin: 0 0 0 2em; 5 | padding: 0; 6 | } 7 | .parsed { 8 | display: none; 9 | } 10 | div.parsed { 11 | max-height: 25em; 12 | } 13 | -------------------------------------------------------------------------------- /prettyjson/static/prettyjson/prettyjson.js: -------------------------------------------------------------------------------- 1 | if (typeof jQuery !== 'undefined' || typeof(django.jQuery) !== 'undefined') { 2 | (function($){ 3 | if (typeof($.fn.JSONView) !== 'undefined') return; 4 | !function(e){var n,t,l,r;return l=function(){function e(e){null==e&&(e={}),this.options=e}return e.prototype.htmlEncode=function(e){return null!==e?e.toString().replace(/&/g,"&").replace(/"/g,""").replace(//g,">"):""},e.prototype.jsString=function(e){return e=JSON.stringify(e).slice(1,-1),this.htmlEncode(e)},e.prototype.decorateWithSpan=function(e,n){return''+this.htmlEncode(e)+""},e.prototype.valueToHTML=function(e,n){var t;return null==n&&(n=0),t=Object.prototype.toString.call(e).match(/\s(.+)]/)[1].toLowerCase(),this[""+t+"ToHTML"].call(this,e,n)},e.prototype.nullToHTML=function(e){return this.decorateWithSpan("null","null")},e.prototype.numberToHTML=function(e){return this.decorateWithSpan(e,"num")},e.prototype.stringToHTML=function(e){var n,t;return/^(http|https|file):\/\/[^\s]+$/i.test(e)?'"'+this.jsString(e)+'"':(n="",e=this.jsString(e),this.options.nl2br&&(t=/([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g,t.test(e)&&(n=" multiline",e=(e+"").replace(t,"$1
"))),'"'+e+'"')},e.prototype.booleanToHTML=function(e){return this.decorateWithSpan(e,"bool")},e.prototype.arrayToHTML=function(e,n){var t,l,r,o,s,i,a,p;for(null==n&&(n=0),l=!1,s="",o=e.length,r=a=0,p=e.length;p>a;r=++a)i=e[r],l=!0,s+="
  • "+this.valueToHTML(i,n+1),o>1&&(s+=","),s+="
  • ",o--;return l?(t=0===n?"":" collapsible",'[
      '+s+"
    ]"):"[ ]"},e.prototype.objectToHTML=function(e,n){var t,l,r,o,s,i,a;null==n&&(n=0),l=!1,s="",o=0;for(i in e)o++;for(i in e)a=e[i],l=!0,r=this.options.escape?this.jsString(i):i,s+='
  • "'+r+'": '+this.valueToHTML(a,n+1),o>1&&(s+=","),s+="
  • ",o--;return l?(t=0===n?"":" collapsible",'{
      '+s+"
    }"):"{ }"},e.prototype.jsonToHTML=function(e){return'
    '+this.valueToHTML(e)+"
    "},e}(),"undefined"!=typeof module&&null!==module&&(module.exports=l),t=function(){function e(){}return e.bindEvent=function(e,n){var t;return t=document.createElement("div"),t.className="collapser",t.innerHTML=n.collapsed?"+":"-",t.addEventListener("click",function(e){return function(t){return e.toggle(t.target,n)}}(this)),e.insertBefore(t,e.firstChild),n.collapsed?this.collapse(t):void 0},e.expand=function(e){var n,t;return t=this.collapseTarget(e),""!==t.style.display?(n=t.parentNode.getElementsByClassName("ellipsis")[0],t.parentNode.removeChild(n),t.style.display="",e.innerHTML="-"):void 0},e.collapse=function(e){var n,t;return t=this.collapseTarget(e),"none"!==t.style.display?(t.style.display="none",n=document.createElement("span"),n.className="ellipsis",n.innerHTML=" … ",t.parentNode.insertBefore(n,t),e.innerHTML="+"):void 0},e.toggle=function(e,n){var t,l,r,o,s,i;if(null==n&&(n={}),r=this.collapseTarget(e),t="none"===r.style.display?"expand":"collapse",n.recursive_collapser){for(l=e.parentNode.getElementsByClassName("collapser"),i=[],o=0,s=l.length;s>o;o++)e=l[o],i.push(this[t](e));return i}return this[t](e)},e.collapseTarget=function(e){var n,t;return t=e.parentNode.getElementsByClassName("collapsible"),t.length?n=t[0]:void 0},e}(),n=e,r={collapse:function(e){return"-"===e.innerHTML?t.collapse(e):void 0},expand:function(e){return"+"===e.innerHTML?t.expand(e):void 0},toggle:function(e){return t.toggle(e)}},n.fn.JSONView=function(){var e,o,s,i,a,p,c;return e=arguments,null!=r[e[0]]?(a=e[0],this.each(function(){var t,l;return t=n(this),null!=e[1]?(l=e[1],t.find(".jsonview .collapsible.level"+l).siblings(".collapser").each(function(){return r[a](this)})):t.find(".jsonview > ul > li .collapsible").siblings(".collapser").each(function(){return r[a](this)})})):(i=e[0],p=e[1]||{},o={collapsed:!1,nl2br:!1,recursive_collapser:!1,escape:!0},p=n.extend(o,p),s=new l({nl2br:p.nl2br,escape:p.escape}),"[object String]"===Object.prototype.toString.call(i)&&(i=JSON.parse(i)),c=s.jsonToHTML(i),this.each(function(){var e,l,r,o,s,i;for(e=n(this),e.html(c),r=e[0].getElementsByClassName("collapsible"),i=[],o=0,s=r.length;s>o;o++)l=r[o],"LI"===l.parentNode.nodeName?i.push(t.bindEvent(l.parentNode,p)):i.push(void 0);return i}))}}($); 5 | 6 | $( document ).ready(function() { 7 | 8 | $('button.parseraw').click(function(e){ 9 | var widget = $(e.target).closest('.jsonwidget'); 10 | var rawarea = widget.find('textarea'); 11 | var parsedarea = widget.find('div.parsed'); 12 | if ($(e.target).text() === 'Show parsed') { 13 | var validjson = true; 14 | try { 15 | JSON.parse(rawarea.val()); 16 | } catch (e) { 17 | validjson = false; 18 | } 19 | if (validjson) { 20 | rawarea.hide(); 21 | widget.find('.parsed').show(); 22 | parsedarea.JSONView(rawarea.val(), {strict: true}).css({ 23 | overflow: "auto", 24 | resize: "both" 25 | }); 26 | $(e.target).text('Show raw'); 27 | } else { 28 | // invalid json 29 | window.alert('Enter valid JSON.'); 30 | } 31 | 32 | } else { 33 | // Clicked Show raw 34 | rawarea.val(JSON.stringify(JSON.parse(rawarea.val()),null,2)); 35 | widget.find('textarea').show(); 36 | widget.find('.parsed').hide(); 37 | $(e.target).text('Show parsed'); 38 | } 39 | }); 40 | $('button.parsed').click(function(e){ 41 | var widget = $(e.target).closest('.jsonwidget'); 42 | var parsedarea = widget.find('div.parsed'); 43 | if ($(e.target).text() === 'Collapse all') { 44 | parsedarea.JSONView('collapse'); 45 | } else { 46 | parsedarea.JSONView('expand'); 47 | } 48 | }); 49 | 50 | $('.jsonwidget').each(function(i) { 51 | if ($(this).attr('data-initial') == 'parsed') { 52 | $(this).find('button.parseraw').click(); 53 | } 54 | }); 55 | 56 | }); 57 | })((typeof jQuery !== 'undefined') ? jQuery : django.jQuery); 58 | } else { 59 | throw new Error('django-prettyjson requires jQuery'); 60 | } 61 | -------------------------------------------------------------------------------- /prettyjson/templates/prettyjson/base.html: -------------------------------------------------------------------------------- 1 | 2 | {% comment %} 3 | As the developer of this package, don't place anything here if you can help it 4 | since this allows developers to have interoperability between your template 5 | structure and their own. 6 | 7 | Example: Developer melding the 2SoD pattern to fit inside with another pattern:: 8 | 9 | {% extends "base.html" %} 10 | {% load static %} 11 | 12 | 13 | {% block extra_js %} 14 | 15 | 16 | {% block javascript %} 17 | 18 | {% endblock javascript %} 19 | 20 | {% endblock extra_js %} 21 | {% endcomment %} 22 | -------------------------------------------------------------------------------- /prettyjson/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinmickey/django-prettyjson/b0dedc7a33228b75f31bcf62c5c283c32d136cf9/prettyjson/templatetags/__init__.py -------------------------------------------------------------------------------- /prettyjson/templatetags/prettyjson.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import json 4 | 5 | from django.template import Library 6 | from django.utils.safestring import mark_safe 7 | 8 | import six 9 | 10 | from ..widgets import PrettyJSONWidget 11 | from standardjson import StandardJSONEncoder 12 | 13 | register = Library() 14 | 15 | 16 | @register.simple_tag 17 | def prettyjson_setup(jquery=True): 18 | widget = PrettyJSONWidget() 19 | media = widget.media 20 | if not jquery: 21 | media._js = media._js[2:] 22 | return mark_safe(str(media)) 23 | 24 | 25 | @register.simple_tag 26 | def prettyjson(obj, name="", **kwargs): 27 | data = obj 28 | if isinstance(obj, six.string_types): 29 | data = json.loads(obj) 30 | widget = PrettyJSONWidget(attrs=kwargs) 31 | return mark_safe(widget.render(name=name, 32 | value=(json.dumps(data, ensure_ascii=False, cls=StandardJSONEncoder)), 33 | attrs=widget.attrs)) 34 | -------------------------------------------------------------------------------- /prettyjson/widgets.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.forms import widgets 3 | 4 | 5 | class PrettyJSONWidget(widgets.Textarea): 6 | 7 | DEFAULT_ATTR = 'raw' 8 | 9 | def render(self, name, value, attrs=None, **kwargs): 10 | html = super(PrettyJSONWidget, self).render(name, value, attrs) 11 | 12 | start_as = self.attrs.get("initial", self.DEFAULT_ATTR) 13 | 14 | if (start_as not in self._allowed_attrs()): 15 | start_as = self.DEFAULT_ATTR 16 | 17 | return ('

    ' + html + '
    ') 22 | 23 | @staticmethod 24 | def _allowed_attrs(): 25 | return (PrettyJSONWidget.DEFAULT_ATTR, 'parsed') 26 | 27 | @property 28 | def media(self): 29 | extra = '' if settings.DEBUG else '.min' 30 | return widgets.Media( 31 | js=( 32 | 'admin/js/vendor/jquery/jquery%s.js' % extra, 33 | 'admin/js/jquery.init.js', 34 | 'prettyjson/prettyjson.js', 35 | ), 36 | css={ 37 | 'all': ('prettyjson/prettyjson.css', ) 38 | }, 39 | ) 40 | -------------------------------------------------------------------------------- /requirements-test.txt: -------------------------------------------------------------------------------- 1 | coverage 2 | mock>=1.0.1 3 | flake8>=2.1.0 4 | tox>=1.7.0 5 | 6 | # Additional test requirements go here 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | django>=1.8 2 | standardjson>=0.3.1 3 | six>=1.10.0 4 | -------------------------------------------------------------------------------- /requirements_dev.txt: -------------------------------------------------------------------------------- 1 | bumpversion==0.5.3 2 | wheel==0.24.0 3 | -------------------------------------------------------------------------------- /runtests.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | try: 4 | from django.conf import settings 5 | from django.test.utils import get_runner 6 | 7 | settings.configure( 8 | DEBUG=True, 9 | USE_TZ=True, 10 | DATABASES={ 11 | "default": { 12 | "ENGINE": "django.db.backends.sqlite3", 13 | } 14 | }, 15 | ROOT_URLCONF="prettyjson.urls", 16 | INSTALLED_APPS=[ 17 | "django.contrib.auth", 18 | "django.contrib.contenttypes", 19 | "django.contrib.sites", 20 | "prettyjson", 21 | ], 22 | SITE_ID=1, 23 | MIDDLEWARE_CLASSES=(), 24 | ) 25 | 26 | try: 27 | import django 28 | setup = django.setup 29 | except AttributeError: 30 | pass 31 | else: 32 | setup() 33 | 34 | except ImportError: 35 | import traceback 36 | traceback.print_exc() 37 | raise ImportError("To fix this error, run: pip install -r requirements-test.txt") 38 | 39 | 40 | def run_tests(*test_args): 41 | if not test_args: 42 | test_args = ['tests'] 43 | 44 | # Run tests 45 | TestRunner = get_runner(settings) 46 | test_runner = TestRunner() 47 | 48 | failures = test_runner.run_tests(test_args) 49 | 50 | if failures: 51 | sys.exit(bool(failures)) 52 | 53 | 54 | if __name__ == '__main__': 55 | run_tests(*sys.argv[1:]) 56 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 0.4.1 3 | commit = True 4 | tag = True 5 | 6 | [bumpversion:file:prettyjson/__init__.py] 7 | 8 | [wheel] 9 | universal = 1 10 | 11 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | import re 5 | import sys 6 | 7 | try: 8 | from setuptools import setup 9 | except ImportError: 10 | from distutils.core import setup 11 | 12 | 13 | def get_version(*file_paths): 14 | filename = os.path.join(os.path.dirname(__file__), *file_paths) 15 | version_file = open(filename).read() 16 | version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", 17 | version_file, re.M) 18 | if version_match: 19 | return version_match.group(1) 20 | raise RuntimeError('Unable to find version string.') 21 | 22 | version = get_version('prettyjson', '__init__.py') 23 | 24 | if sys.argv[-1] == 'publish': 25 | try: 26 | import wheel 27 | except ImportError: 28 | print('Wheel library missing. Please run "pip install wheel"') 29 | sys.exit() 30 | os.system('python setup.py sdist upload') 31 | os.system('python setup.py bdist_wheel upload') 32 | sys.exit() 33 | 34 | # bumpversion does this 35 | # if sys.argv[-1] == 'tag': 36 | # print("Tagging the version on github:") 37 | # os.system("git tag -a %s -m 'version %s'" % (version, version)) 38 | # os.system("git push --tags") 39 | # sys.exit() 40 | 41 | readme = open('README.md').read() 42 | history = open('HISTORY.rst').read().replace('.. :changelog:', '') 43 | 44 | setup( 45 | name='django-prettyjson', 46 | version=version, 47 | description="""Enables pretty JSON viewer in Django forms, admin, or templates""", 48 | long_description=readme + '\n\n' + history, 49 | author='Kevin Mickey', 50 | author_email='kwmickey@gmail.com', 51 | url='https://github.com/kevinmickey/django-prettyjson', 52 | packages=[ 53 | 'prettyjson', 54 | ], 55 | include_package_data=True, 56 | install_requires=[ 57 | 'django>=1.8', 58 | 'standardjson>=0.3.1', 59 | 'six>=1.10.0' 60 | ], 61 | license="BSD", 62 | zip_safe=False, 63 | keywords='django-prettyjson', 64 | classifiers=[ 65 | 'Development Status :: 3 - Alpha', 66 | 'Framework :: Django', 67 | 'Framework :: Django :: 1.8', 68 | 'Framework :: Django :: 1.9', 69 | 'Intended Audience :: Developers', 70 | 'License :: OSI Approved :: BSD License', 71 | 'Natural Language :: English', 72 | 'Programming Language :: Python :: 2', 73 | 'Programming Language :: Python :: 2.7', 74 | 'Programming Language :: Python :: 3', 75 | 'Programming Language :: Python :: 3.4', 76 | 'Programming Language :: Python :: 3.5', 77 | ], 78 | ) 79 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kevinmickey/django-prettyjson/b0dedc7a33228b75f31bcf62c5c283c32d136cf9/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_models.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | test_django-prettyjson 6 | ------------ 7 | 8 | Tests for `django-prettyjson` models module. 9 | """ 10 | 11 | from django.test import TestCase 12 | 13 | # from prettyjson import models 14 | 15 | 16 | class TestPrettyjson(TestCase): 17 | 18 | def setUp(self): 19 | pass 20 | 21 | def test_something(self): 22 | pass 23 | 24 | def tearDown(self): 25 | pass 26 | -------------------------------------------------------------------------------- /tests/test_prettyjson.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | import mock 3 | 4 | from prettyjson import PrettyJSONWidget 5 | 6 | 7 | class TestPrettyJson(TestCase): 8 | def test_widget_without_args_renders_raw_view(self): 9 | widget = PrettyJSONWidget() 10 | 11 | result = widget.render(mock.MagicMock(), mock.MagicMock()) 12 | 13 | self.assertIn('data-initial="raw"', result) 14 | 15 | def test_widget_renders_parsed_view_when_requested(self): 16 | widget = PrettyJSONWidget(attrs={'initial': 'parsed'}) 17 | 18 | result = widget.render(mock.MagicMock(), mock.MagicMock()) 19 | 20 | self.assertIn('data-initial="parsed"', result) 21 | 22 | def test_widget_renders_raw_view_when_requested(self): 23 | widget = PrettyJSONWidget(attrs={'initial': 'raw'}) 24 | 25 | result = widget.render(mock.MagicMock(), mock.MagicMock()) 26 | 27 | self.assertIn('data-initial="raw"', result) 28 | 29 | def test_widget_renders_raw_view_when_invalid_requested(self): 30 | widget = PrettyJSONWidget(attrs={'initial': 'invalid_view'}) 31 | 32 | result = widget.render(mock.MagicMock(), mock.MagicMock()) 33 | 34 | self.assertIn('data-initial="raw"', result) 35 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = py27, py34, py35 3 | 4 | [testenv] 5 | setenv = 6 | PYTHONPATH = {toxinidir}:{toxinidir}/prettyjson 7 | commands = python runtests.py 8 | deps = 9 | -r{toxinidir}/requirements-test.txt 10 | --------------------------------------------------------------------------------