{ "info": { "author": "Harvard Business School, HBX Department", "author_email": "pnore@hbs.edu", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Framework :: Django", "Framework :: Django :: 1.10", "Framework :: Django :: 1.11", "Framework :: Django :: 1.9", "Framework :: Django :: 2.0", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6" ], "description": "Django Elastic Migrations\n=========================\n\n`django-elastic-migrations`_ is a Django app for creating, indexing and changing schemas of Elasticsearch indexes.\n\n\n.. image:: https://travis-ci.com/HBS-HBX/django-elastic-migrations.svg?branch=master\n :target: https://travis-ci.com/HBS-HBX/django-elastic-migrations\n :alt: Build Status\n\n\n.. image:: https://codecov.io/gh/HBS-HBX/django-elastic-migrations/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/HBS-HBX/django-elastic-migrations\n :alt: codecov\n\n.. _django-elastic-migrations: https://pypi.org/project/django-elastic-migrations/\n\nOverview\n--------\n\nElastic has given us basic python tools for working with its search indexes:\n\n* `elasticsearch-py`_, a python interface to elasticsearch's REST API\n* `elasticsearch-dsl-py`_, a Django-esque way of declaring Elasticsearch schemas,\n built upon `elasticsearch-py`_\n\nDjango Elastic Migrations adapts these tools into a Django app which also:\n\n* Provides Django management commands for ``list``\\ ing indexes, as well as performing\n ``create``, ``update``, ``activate`` and ``drop`` actions on them\n* Implements concurrent bulk indexing powered by python ``multiprocessing``\n* Gives Django test hooks for Elasticsearch\n* Records a history of all actions that change Elasticsearch indexes\n* Supports AWS Elasticsearch 6.0, 6.1 (6.2 TBD; see `#3 support elasticsearch-dsl 6.2`_)\n* Enables having two or more servers share the same Elasticsearch cluster\n\n.. _elasticsearch-py: https://github.com/elastic/elasticsearch-py\n.. _elasticsearch-dsl-py: https://github.com/elastic/elasticsearch-dsl-py\n.. _#3 support elasticsearch-dsl 6.2: https://github.com/HBS-HBX/django-elastic-migrations/issues/3\n\n\nModels\n^^^^^^\n\nDjango Elastic Migrations provides comes with three Django models:\n**Index**, **IndexVersion**, and **IndexAction**:\n\n* \n **Index** - a logical reference to an Elasticsearch index.\n Each ``Index`` points to multiple ``IndexVersions``, each of which contains\n a snapshot of that ``Index`` schema at a particular time. Each ``Index`` has an\n *active* ``IndexVersion`` to which all actions are directed.\n\n* \n **IndexVersion** - a snapshot of an Elasticsearch ``Index`` schema at a particular\n point in time. The Elasticsearch index name is the name of the *Index* plus the\n primary key id of the ``IndexVersion`` model, e.g. ``movies-1``. When the schema is\n changed, a new ``IndexVersion`` is added with name ``movies-2``, etc.\n\n* \n **IndexAction** - a record of a change that impacts an ``Index``, such as updating\n the index or changing which ``IndexVersion`` is active in an ``Index``.\n\nManagement Commands\n^^^^^^^^^^^^^^^^^^^\n\nUse ``./manage.py es --help`` to see the list of all of these commands.\n\nRead Only Commands\n~~~~~~~~~~~~~~~~~~\n\n\n* ``./manage.py es_list``\n\n * help: For each *Index*\\ , list activation status and doc\n count for each of its *IndexVersions*\n * usage: ``./manage.py es_list``\n\nAction Commands\n~~~~~~~~~~~~~~~\n\nThese management commands add an Action record in the database,\nso that the history of each *Index* is recorded.\n\n\n* ``./manage.py es_create`` - create a new index.\n* ``./manage.py es_activate`` - *activate* a new ``IndexVersion``. all\n updates and reads for that ``Index`` by will then go to that version.\n* ``./manage.py es_update`` - update the documents in the index.\n* ``./manage.py es_clear`` - remove the documents from an index.\n* ``./manage.py es_drop`` - drop an index.\n* ``./manage.py es_dangerous_reset`` - erase elasticsearch and reset the\n Django Elastic Migrations models.\n\nFor each of these, use ``--help`` to see the details.\n\nUsage\n^^^^^\n\nInstallation\n~~~~~~~~~~~~\n\n#. ``pip install django-elastic-migrations``; see `django-elastic-migrations`_ on PyPI\n#. Put a reference to this package in your ``requirements.txt``\n#. Ensure that a valid ``elasticsearch-dsl-py`` version is accessible, and configure\n the path to your configured Elasticsearch singleton client in your django settings:\n ``DJANGO_ELASTIC_MIGRATIONS_ES_CLIENT = \"tests.es_config.ES_CLIENT\"``.\n There should only be one ``ES_CLIENT`` instantiated in your application.\n#. Add ``django_elastic_migrations`` to ``INSTALLED_APPS`` in your Django\n settings file\n#. Add the following information to your Django settings file:\n ::\n\n DJANGO_ELASTIC_MIGRATIONS_ES_CLIENT = \"path.to.your.singleton.ES_CLIENT\"\n # optional, any unique number for your releases to associate with indexes\n DJANGO_ELASTIC_MIGRATIONS_GET_CODEBASE_ID = subprocess.check_output(['git', 'describe', \"--tags\"]).strip()\n # optional, can be used to have multiple servers share the same \n # elasticsearch instance without conflicting\n DJANGO_ELASTIC_MIGRATIONS_ENVIRONMENT_PREFIX = \"qa1_\"\n\n#. Create the ``django_elastic_migrations`` tables by running ``./manage.py migrate``\n#. Create an ``DEMIndex``:\n ::\n\n from django_elastic_migrations.indexes import DEMIndex, DEMDocType\n from .models import Movie\n from elasticsearch_dsl import Text\n\n MoviesIndex = DEMIndex('movies')\n\n\n @MoviesIndex.doc_type\n class MovieSearchDoc(DEMDocType):\n text = TEXT_COMPLEX_ENGLISH_NGRAM_METAPHONE\n\n @classmethod\n def get_queryset(self, last_updated_datetime=None):\n \"\"\"\n return a queryset or a sliceable list of items to pass to\n get_reindex_iterator\n \"\"\"\n qs = Movie.objects.all()\n if last_updated_datetime:\n qs.filter(last_modified__gt=last_updated_datetime)\n return qs\n\n @classmethod\n def get_reindex_iterator(self, queryset):\n return [\n MovieSearchDoc(\n text=\"a little sample text\").to_dict(\n include_meta=True) for g in queryset]\n\n\n#. Add your new index to DJANGO_ELASTIC_MIGRATIONS_INDEXES in settings/common.py\n\n#. Run ``./manage.py es_list`` to see the index as available:\n ::\n\n ./manage.py es_list\n\n Available Index Definitions:\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n | Index Base Name | Index Version Name | Created | Active | Docs | Tag |\n +======================+=====================================+=========+========+=======+===========+\n | movies | | 0 | 0 | 0 | Current |\n | | | | | | (not |\n | | | | | | created) |\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n Reminder: an index version name looks like 'my_index-4', and its base index name\n looks like 'my_index'. Most Django Elastic Migrations management commands\n take the base name (in which case the activated version is used)\n or the specific index version name.\n\n\n#. Create the ``movies`` index in elasticsearch with ``./manage.py es_create movies``:\n ::\n\n $> ./manage.py es_create movies\n The doc type for index 'movies' changed; created a new index version\n 'movies-1' in elasticsearch.\n $> ./manage.py es_list\n\n Available Index Definitions:\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n | Index Base Name | Index Version Name | Created | Active | Docs | Tag |\n +======================+=====================================+=========+========+=======+===========+\n | movies | movies-1 | 1 | 0 | 0 | 07.11.005 |\n | | | | | | -93-gd101 |\n | | | | | | a1f |\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n\n Reminder: an index version name looks like 'my_index-4', and its base index name \n looks like 'my_index'. Most Django Elastic Migrations management commands \n take the base name (in which case the activated version is used) \n or the specific index version name.\n\n#. Activate the ``movies-1`` index version, so all updates and reads go to it.\n ::\n\n ./manage.py es_activate movies\n For index 'movies', activating 'movies-1' because you said so.\n\n#. Assuming you have implemented ``get_reindex_iterator``, you can call\n ``./manage.py es_update`` to update the index.\n ::\n\n $> ./manage.py es_update movies\n\n Handling update of index 'movies' using its active index version 'movies-1'\n Checking the last time update was called: \n - index version: movies-1\n - update date: never \n Getting Reindex Iterator...\n Completed with indexing movies-1\n\n $> ./manage.py es_list\n\n Available Index Definitions:\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n | Index Base Name | Index Version Name | Created | Active | Docs | Tag |\n +======================+=====================================+=========+========+=======+===========+\n | movies | movies-1 | 1 | 1 | 3 | 07.11.005 |\n | | | | | | -93-gd101 |\n | | | | | | a1f |\n +----------------------+-------------------------------------+---------+--------+-------+-----------+\n\nDeployment\n^^^^^^^^^^\n\n\n* Creating and updating a new index schema can happen before you deploy.\n For example, if your app servers are running with the ``movies-1`` index activated, and you\n have a new version of the schema you'd like to pre-index, then log into another\n server and run ``./manage.py es_create movies`` followed by\n ``./manage.py es_update movies --newer``. This will update documents in all ``movies``\n indexes that are newer than the active one.\n* After deploying, you can run\n ``./manage.py es_activate movies`` to activate the latest version. Be sure to cycle your\n gunicorn workers to ensure the change is caught by your app servers.\n* During deployment, if ``get_reindex_iterator`` is implemented in such a way as to respond\n to the datetime of the last reindex date, then you can call\n ``./manage.py es_update movies --resume``, and it will index *only those documents that have\n changed since the last reindexing*. This way you can do most of the indexing ahead of time,\n and only reindex a portion at the time of the deployment.\n\nDjango Testing\n^^^^^^^^^^^^^^\n\n\n#. (optional) update ``DJANGO_ELASTIC_MIGRATIONS_ENVIRONMENT_PREFIX`` in\n your Django settings. The default test prefix is ``test_``. Every\n test will create its own indexes.\n ::\n\n if 'test' in sys.argv:\n DJANGO_ELASTIC_MIGRATIONS_ENVIRONMENT_PREFIX = 'test_'\n\n#. Override TestCase - ``test_utilities.py``\n\n .. code-block::\n\n from django_elastic_migrations import DEMIndexManager\n\n class MyTestCase(TestCase):\n\n def _pre_setup(self):\n DEMIndexManager.test_pre_setup()\n super(MyTestCase, self)._pre_setup()\n\n def _post_teardown(self):\n DEMIndexManager.test_post_teardown()\n super(MyTestCase, self)._post_teardown()\n\nExcluding from Django's ``dumpdata`` command\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nWhen calling `django's dumpdata command `_\\,\nyou likely will want to exclude the database tables used in this app:\n\n::\n\n from django.core.management import call_command\n params = {\n 'database': 'default',\n 'exclude': [\n # we don't want to include django_elastic_migrations in dumpdata, \n # because it's environment specific\n 'django_elastic_migrations.index',\n 'django_elastic_migrations.indexversion',\n 'django_elastic_migrations.indexaction'\n ],\n 'indent': 3,\n 'output': 'path/to/my/file.json'\n }\n call_command('dumpdata', **params)\n\nAn example of this is included with the\n`moviegen management command`_.\n\n.. _moviegen management command: https://github.com/HBS-HBX/django-elastic-migrations/blob/master/tests/management/commands/moviegen.py\n\nTuning Bulk Indexing Parameters\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nBy default, ``/.manage.py es_update`` will divide the result of \n``DEMDocType.get_queryset()`` into batches of size ``DocType.BATCH_SIZE``. \nOverride this number to change the batch size. \n\nThere are many configurable paramters to Elasticsearch's `bulk updater `_.\nTo provide a custom value, override ``DEMDocType.get_bulk_indexing_kwargs()``\nand return the kwargs you would like to customize.\n\nDevelopment\n-----------\n\nThis project uses ``make`` to manage the build process. Type ``make help``\nto see the available ``make`` targets.\n\nElasticsearch Docker Compose\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n``docker-compose -f local.yml up``\n\n`See docs/docker_setup for more info <./docs/docker_setup.rst>`_\n\nRequirements\n^^^^^^^^^^^^\nThis project uses `pip-tools`_. The ``requirements.txt`` files are generated\nand pinned to latest versions with ``make upgrade``:\n\n* run ``make requirements`` to run the pip install.\n\n* run ``make upgrade`` to upgrade the dependencies of the requirements to the latest\n versions. This process also excludes ``django`` and ``elasticsearch-dsl``\n from the ``requirements/test.txt`` so they can be injected with different\n versions by tox during matrix testing.\n\n.. _pip-tools: https://github.com/jazzband/pip-tools\n\n\nPopulating Local ``tests_movies`` Database Table With Data\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nIt may be helpful for you to populate a local database with Movies test\ndata to experiment with using ``django-elastic-migrations``. First,\nmigrate the database:\n\n``./manage.py migrate --run-syncdb --settings=test_settings``\n\nNext, load the basic fixtures:\n\n``./manage.py loaddata tests/100films.json``\n\nYou may wish to add more movies to the database. A management command\nhas been created for this purpose. Get a `Free OMDB API key here `_\\ ,\nthen run a query like this (replace ``MYAPIKEY`` with yours):\n\n.. code-block::\n\n $> ./manage.py moviegen --title=\"Inception\" --api-key=\"MYAPIKEY\"\n {'actors': 'Leonardo DiCaprio, Joseph Gordon-Levitt, Ellen Page, Tom Hardy',\n 'awards': 'Won 4 Oscars. Another 152 wins & 204 nominations.',\n 'boxoffice': '$292,568,851',\n 'country': 'USA, UK',\n 'director': 'Christopher Nolan',\n 'dvd': '07 Dec 2010',\n 'genre': 'Action, Adventure, Sci-Fi',\n 'imdbid': 'tt1375666',\n 'imdbrating': '8.8',\n 'imdbvotes': '1,721,888',\n 'language': 'English, Japanese, French',\n 'metascore': '74',\n 'plot': 'A thief, who steals corporate secrets through the use of '\n 'dream-sharing technology, is given the inverse task of planting an '\n 'idea into the mind of a CEO.',\n 'poster': 'https://m.media-amazon.com/images/M/MV5BMjAxMzY3NjcxNF5BMl5BanBnXkFtZTcwNTI5OTM0Mw@@._V1_SX300.jpg',\n 'production': 'Warner Bros. Pictures',\n 'rated': 'PG-13',\n 'ratings': [{'Source': 'Internet Movie Database', 'Value': '8.8/10'},\n {'Source': 'Rotten Tomatoes', 'Value': '86%'},\n {'Source': 'Metacritic', 'Value': '74/100'}],\n 'released': '16 Jul 2010',\n 'response': 'True',\n 'runtime': 148,\n 'title': 'Inception',\n 'type': 'movie',\n 'website': 'http://inceptionmovie.warnerbros.com/',\n 'writer': 'Christopher Nolan',\n 'year': '2010'}\n\nTo save the movie to the database, use the ``--save`` flag. Also useful is\nthe ``--noprint`` option, to suppress json. Also, if you add\n``OMDB_API_KEY=MYAPIKEY`` to your environment variables, you don't have\nto specify it each time:\n\n.. code-block::\n\n $ ./manage.py moviegen --title \"Closer\" --noprint --save\n Saved 1 new movie(s) to the database: Closer\n\nNow that it's been saved to the database, you may want to create a fixture,\nso you can get back to this state in the future.\n\n.. code-block::\n\n $ ./manage.py moviegen --makefixture=tests/myfixture.json\n dumping fixture data to tests/myfixture.json ...\n [...........................................................................]\n\nLater, you can restore this database with the regular ``loaddata`` command:\n\n.. code-block::\n\n $ ./manage.py loaddata tests/myfixture.json\n Installed 101 object(s) from 1 fixture(s)\n\nThere are already 100 films available using ``loaddata`` as follows:\n\n.. code-block::\n\n $ ./manage.py loaddata tests/100films.json\n\nRunning Tests Locally\n^^^^^^^^^^^^^^^^^^^^^\n\nRun ``make test``. To run all tests and quality checks locally,\nrun ``make test-all``.\n\nTo just run linting, ``make quality``. Please note that if any of the\nlinters return a nonzero code, it will give an ``InvocationError`` error\nat the end. See `tox's documentation for InvocationError`_ for more information.\n\nWe use ``edx_lint`` to compile ``pylintrc``. To update the rules,\nchange ``pylintrc_tweaks`` and run ``make pylintrc``.\n\n.. _tox's documentation for InvocationError: https://tox.readthedocs.io/en/latest/example/general.html#understanding-invocationerror-exit-codes\n\nCutting a New Version\n^^^^^^^^^^^^^^^^^^^^^\n\n* optional: run ``make update`` to update dependencies\n* bump version in `django_elastic_migrations/__init__.py `_.\n* update `CHANGELOG.rst `_.\n* ``make clean``\n* ``python3 setup.py sdist bdist_wheel``\n* ``twine check dist/django-elastic-migrations-*.tar.gz`` to see if there are any syntax mistakes before tagging\n* submit PR bumping the version\n* ensure test matrix is passing on travis and merge PR\n* pull changes to master\n* ``make clean``\n* ``python3 setup.py sdist bdist_wheel``\n* ``twine check dist/django-elastic-migrations-*.tar.gz`` to see if there are any syntax mistakes before tagging\n* ``twine upload -r testpypi dist/django-elastic-migrations-*.tar.gz``\n* `Check it at https://test.pypi.org/project/django-elastic-migrations/ `_\n* ``python3 setup.py tag`` to tag the new version\n* ``twine upload -r pypi dist/django-elastic-migrations-*.tar.gz``\n* `Update new release at https://github.com/HBS-HBX/django-elastic-migrations/releases `_\n\n\nChangelog\n---------\n\n0.8.2 (2018-11-20)\n^^^^^^^^^^^^^^^^^^\n* fix `#59 twine check error in 0.8.1 `_\n\n0.8.1 (2018-11-19)\n^^^^^^^^^^^^^^^^^^\n* fix `#50 add test coverage for es_list `_\n* fix `#58 ignore indexes with a dot in name in es_list --es-only and es_dangerous_reset `_\n\n0.8.0 (2018-11-13)\n^^^^^^^^^^^^^^^^^^\n* fix `#6 support Django 2 `_\n* fix `#43 remove es_deactivate `_\n* fix `#44 add django 1.10 and 1.11 to test matrix `_\n* fix `#45 remove support for python 2 `_\n* In practice, Python 2 may work, but it is removed from the test matrix and won't be updated\n\n0.7.8 (2018-11-13)\n^^^^^^^^^^^^^^^^^^\n* fix `#7 Convert Readme to rst for pypi `_\n* first release on PyPI\n* update project dependencies\n\n0.7.7 (2018-09-17)\n^^^^^^^^^^^^^^^^^^\n* fix `#41 stack trace when indexing in py3 `_\n\n0.7.6 (2018-09-11)\n^^^^^^^^^^^^^^^^^^\n* fix `#36 es_update --start flag broken `_\n\n0.7.5 (2018-08-20)\n^^^^^^^^^^^^^^^^^^\n* fix `#35 open multiprocessing log in context handler `_\n\n0.7.4 (2018-08-15)\n^^^^^^^^^^^^^^^^^^\n* fix `#33 error when nothing to resume using --resume `_\n\n0.7.3 (2018-08-14)\n^^^^^^^^^^^^^^^^^^\n* fix #31 es_update movies --newer --workers does not store worker information\n\n0.7.2 (2018-08-13)\n^^^^^^^^^^^^^^^^^^\n* fix #21 wrong batch update total using multiprocessing in 0.7.1\n* fix #23 KeyError _index_version_name in es_update --newer\n* address #25 use pks for queryset inside workers #29\n\n0.7.1 (2018-08-07)\n^^^^^^^^^^^^^^^^^^\n* fixed gh #8 es_dangerous_reset --es-only to sync database to ES\n* fixed gh #17 make es_dangerous_reset remove dem models\n* improved test coverage\n* added tests for ``es_create --es-only``\n* added ``IndexVersion.hard_delete()`` (not called by default)\n* added ``hard_delete`` flag to ``DropIndexAction``\n* added ``hard_delete`` flag to ``DEMIndexManager.test_post_teardown()``\n* updated ``__str__()`` of ``IndexAction`` to be more descriptive\n\n0.7.0 (2018-08-06)\n^^^^^^^^^^^^^^^^^^\n* fixed gh #5: \"add python 3 support and tests\"\n\n0.6.1 (2018-08-03)\n^^^^^^^^^^^^^^^^^^\n* fixed gh #9: \"using elasticsearch-dsl 6.1, TypeError in DEMIndex.save\"\n\n0.6.0 (2018-08-01)\n^^^^^^^^^^^^^^^^^^\n* Added test structure for py2 - GH #2\n* Renamed default log handler from ``django-elastic-migrations`` to ``django_elastic_migrations``\n\n0.5.3 (2018-07-23)\n^^^^^^^^^^^^^^^^^^\n* First basic release", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/HBS-HBX/django-elastic-migrations", "keywords": "Django Elasticsearch", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "django-elastic-migrations", "package_url": "https://pypi.org/project/django-elastic-migrations/", "platform": "", "project_url": "https://pypi.org/project/django-elastic-migrations/", "project_urls": { "Homepage": "https://github.com/HBS-HBX/django-elastic-migrations" }, "release_url": "https://pypi.org/project/django-elastic-migrations/0.8.2/", "requires_dist": null, "requires_python": "", "summary": "Manage Elasticsearch Indexes in Django", "version": "0.8.2" }, "last_serial": 4503370, "releases": { "0.7.8": [ { "comment_text": "", "digests": { "md5": "82acdc04c5c253767ec43f59cb1cb57e", "sha256": "b68322c99351de3013d54a8f1063e4bc1ef6bfc42d50e2e37b6c04901d8e82b4" }, "downloads": -1, "filename": "django-elastic-migrations-0.7.8.tar.gz", "has_sig": false, "md5_digest": "82acdc04c5c253767ec43f59cb1cb57e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49005, "upload_time": "2018-11-13T14:28:26", "url": "https://files.pythonhosted.org/packages/a7/0d/e34021d2810833612d620bd1b977d977dba9e609d6efb69a2746da2ce8a7/django-elastic-migrations-0.7.8.tar.gz" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "c9bda9ed7f79b07570a867efcd4ff530", "sha256": "7f7bbe19c5fb214aa451f1f28a02f07deefd6c71f2405cd021e8d3db7b78241a" }, "downloads": -1, "filename": "django-elastic-migrations-0.8.0.tar.gz", "has_sig": false, "md5_digest": "c9bda9ed7f79b07570a867efcd4ff530", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48819, "upload_time": "2018-11-13T17:56:46", "url": "https://files.pythonhosted.org/packages/01/a4/13d1acbca59e84615cd5692579bb12c3f86b0311b568656724bc19ed8706/django-elastic-migrations-0.8.0.tar.gz" } ], "0.8.2": [ { "comment_text": "", "digests": { "md5": "21f9ffc0f3ad74e8704f52dfdac7d061", "sha256": "5de4637493409634a8ac1735e060e7f4bcfe95ac37ed2b8b662ef2a86f729590" }, "downloads": -1, "filename": "django-elastic-migrations-0.8.2.tar.gz", "has_sig": false, "md5_digest": "21f9ffc0f3ad74e8704f52dfdac7d061", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49703, "upload_time": "2018-11-19T15:24:26", "url": "https://files.pythonhosted.org/packages/95/d9/63b09cb79e0f8c3f4dc4530227ef8b9eba8320a1b43bc0d00288618bce10/django-elastic-migrations-0.8.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "21f9ffc0f3ad74e8704f52dfdac7d061", "sha256": "5de4637493409634a8ac1735e060e7f4bcfe95ac37ed2b8b662ef2a86f729590" }, "downloads": -1, "filename": "django-elastic-migrations-0.8.2.tar.gz", "has_sig": false, "md5_digest": "21f9ffc0f3ad74e8704f52dfdac7d061", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49703, "upload_time": "2018-11-19T15:24:26", "url": "https://files.pythonhosted.org/packages/95/d9/63b09cb79e0f8c3f4dc4530227ef8b9eba8320a1b43bc0d00288618bce10/django-elastic-migrations-0.8.2.tar.gz" } ] }