{ "info": { "author": "Aymeric Augustin", "author_email": "aymeric.augustin@m4x.org", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.11", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7" ], "description": "django-sequences\n################\n\nThe problem\n===========\n\nDjango's default, implicit primary keys aren't guaranteed to be sequential.\n\nIf a transaction inserts a row and then is rolled back, the sequence counter\nisn't rolled back for performance reasons, creating a gap in primary keys.\n\nThis can cause compliance issues for some use cases such as accounting.\n\nThis risk isn't well known. Since most transactions succeed, values look\nsequential. Gaps will only be revealed by audits.\n\nThe solution\n============\n\ndjango-sequences provides a ``get_next_value`` function which is designed to\nbe used as follows::\n\n from django.db import transaction\n\n from sequences import get_next_value\n\n from invoices.models import Invoice\n\n with transaction.atomic():\n Invoice.objects.create(number=get_next_value('invoice_numbers'))\n\n**The guarantees of django-sequences only apply if you call** ``get_next_value``\n**and save its return value to the database within the same transaction!**\n\nInstallation\n============\n\ndjango-sequences is compatible with Django 1.11 (LTS), 2.1 and 2.2.\n\nInstall django-sequences::\n\n $ pip install django-sequences\n\nAdd it to the list of applications in your project's settings::\n\n INSTALLED_APPS += ['sequences.apps.SequencesConfig']\n\nRun migrations::\n\n $ django-admin migrate\n\nAPI\n===\n\n``get_next_value``\n------------------\n\n::\n\n >>> from sequences import get_next_value\n\nThis function generates a gapless sequence of integer values::\n\n >>> get_next_value()\n 1\n >>> get_next_value()\n 2\n >>> get_next_value()\n 3\n\nIt supports multiple independent sequences::\n\n >>> get_next_value('cases')\n 1\n >>> get_next_value('cases')\n 2\n >>> get_next_value('invoices')\n 1\n >>> get_next_value('invoices')\n 2\n\nThe first value defaults to 1. It can be customized::\n\n >>> get_next_value('customers', initial_value=1000) # pro growth hacking\n\nThe ``initial_value`` parameter only matters when ``get_next_value`` is called\nfor the first time for a given sequence \u2014 assuming the corresponding database\ntransaction gets committed; as discussed above, if the transaction is rolled\nback, the generated value isn't consumed. It's also possible to initialize a\nsequence in a data migration and not use ``initial_value`` in actual code.\n\nSequences can loop::\n\n >>> get_next_value('seconds', initial_value=0, reset_value=60)\n\nWhen the sequence reaches ``reset_value``, it restarts at ``initial_value``.\nIn other works, it generates ``reset_value - 2``, ``reset_value - 1``,\n``initial_value``, ``initial_value + 1``, etc. In that case, each call to\n``get_next_value`` must provide ``initial_value`` when it isn't the default\nand ``reset_value``.\n\n**Database transactions that call** ``get_next_value`` **for a given sequence\nare serialized.** In other words, when you call ``get_next_value`` in a\ndatabase transaction, other callers trying to get a value from the same\nsequence block until the transaction completes, either with a commit or a\nrollback. You should keep such transactions short to minimize the impact on\nperformance.\n\nThis is why databases default to a faster behavior that may create gaps.\n\nPassing ``nowait=True`` makes ``get_next_value`` raise an exception instead of\nblocking in this scenario. This is rarely useful. Also it doesn't work for the\nfirst call. (Arguably this is a bug. Patches welcome.)\n\nCalls to ``get_next_value`` for distinct sequences don't interact with one\nanother.\n\nFinally, passing ``using='...'`` allows selecting the database on which the\ncurrent sequence value is stored. When this parameter isn't provided, it\ndefaults to the default database for writing models of the ``sequences``\napplication. See \"Multiple databases\" below for details.\n\nTo sum up, the complete signature of ``get_next_value`` is::\n\n get_next_value(\n sequence_name='default',\n initial_value=1,\n reset_value=None,\n *,\n nowait=False,\n using=None,\n )\n\nUnder the hood, ``get_next_value`` relies on the database's transactional\nintegrity to guarantee that each value is returned exactly once.\n\n``get_last_value``\n------------------\n\n::\n\n >>> from sequences import get_last_value\n\nThis function returns the last value generated by a sequence::\n\n >>> get_last_value()\n None\n >>> get_next_value()\n 1\n >>> get_last_value()\n 1\n >>> get_next_value()\n 2\n >>> get_last_value()\n 2\n\nIf the sequence hasn't generated a value yet, ``get_last_value`` returns\n``None``.\n\nIt supports independent sequences like ``get_next_value``::\n\n >>> get_next_value('cases')\n 1\n >>> get_last_value('cases')\n 1\n >>> get_next_value('invoices')\n 1\n >>> get_last_value('invoices')\n 1\n\nIt accepts ``using='...'`` for selecting the database on which the current\nsequence value is stored, defaulting to the default database for reading\nmodels of the ``sequences`` application.\n\nThe complete signature of ``get_last_value`` is::\n\n get_last_value(\n sequence_name='default',\n *,\n using=None,\n )\n\n``get_last_value`` **is a convenient and fast way to tell how many values a\nsequence generated but it makes no guarantees.** Concurrent calls to\n``get_next_value`` may produce unexpected results of ``get_last_value``.\n\n``Sequence``\n------------\n\n::\n\n >>> from sequences import Sequence\n\n(not to be confused with ``sequences.models.Sequence``, a private API)\n\nThis class stores parameters for a sequence and provides ``get_next_value``\nand ``get_last_value`` methods::\n\n >>> claim_ids = Sequence('claims')\n >>> claim_ids.get_next_value()\n 1\n >>> claim_ids.get_next_value()\n 2\n >>> claim_ids.get_last_value()\n 2\n\nThis reduces the risk of errors when the same sequence is used in multiple\nplaces.\n\nInstances of ``Sequence`` are also infinite iterators::\n\n >>> next(claim_ids)\n 3\n >>> next(claim_ids)\n 4\n\nThe complete API is::\n\n Sequence(\n sequence_name='default',\n initial_value=1,\n reset_value=None,\n *,\n using=None,\n )\n\n Sequence.get_next_value(\n self,\n *,\n nowait=False\n )\n\n Sequence.get_last_value(\n self,\n )\n\nAll parameters have the same meaning as in the ``get_next_value`` and\n``get_last_value`` functions.\n\n\nContributing\n============\n\nYou can run tests with::\n\n $ make test\n\nIf you'd like to contribute, please open an issue or a pull request on GitHub!\n\nDatabase support\n================\n\ndjango-sequences is tested on PostgreSQL, MySQL, Oracle, and SQLite.\n\nMySQL only supports the ``nowait`` parameter when it's MariaDB \u2265 8.0.1.\n\nApplications that will only ever be deployed with an SQLite database don't\nneed django-sequences because SQLite's ``INTEGER PRIMARY KEY AUTOINCREMENT``\nfields are guaranteed to be sequential.\n\nMultiple databases\n==================\n\nSince django-sequences relies on the database to guarantee transactional\nintegrity, the current value for a given sequence must be stored in the same\ndatabase as models containing generated values.\n\nIn a project that uses multiple databases, you must write a suitable database\nrouter to create tables for the ``sequences`` application on all databases\nstoring models containing sequential numbers.\n\nEach database has its own namespace: a sequence with the same name stored in\ntwo databases will have independent counters in each database.\n\nChangelog\n=========\n\n2.4\n---\n\n* Add the ``get_last_value`` function.\n* Add the ``Sequence`` class.\n\n2.3\n---\n\n* Optimize performance on MySQL.\n* Test on MySQL, SQLite and Oracle.\n\n2.2\n---\n\n* Optimize performance on PostgreSQL \u2265 9.5.\n\n2.1\n---\n\n* Provide looping sequences with ``reset_value``.\n\n2.0\n---\n\n* Add support for multiple databases.\n* Add translations.\n* ``nowait`` becomes keyword-only argument.\n* Drop support for Python 2.\n\n1.0\n---\n\n* Initial stable release.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/aaugustin/django-sequences", "keywords": "", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "django-sequences", "package_url": "https://pypi.org/project/django-sequences/", "platform": "", "project_url": "https://pypi.org/project/django-sequences/", "project_urls": { "Homepage": "https://github.com/aaugustin/django-sequences" }, "release_url": "https://pypi.org/project/django-sequences/2.4/", "requires_dist": null, "requires_python": "", "summary": "Generate gapless sequences of integer values.", "version": "2.4" }, "last_serial": 5559998, "releases": { "1.0": [ { "comment_text": "", "digests": { "md5": "20ee74c0aea2af0e9f4b6fd6cb33dbc9", "sha256": "e569c2edbdbc155a39398763b004f9629bf0375399760d3e4a66036d47de60e9" }, "downloads": -1, "filename": "django_sequences-1.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "20ee74c0aea2af0e9f4b6fd6cb33dbc9", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 10062, "upload_time": "2016-01-05T20:43:44", "url": "https://files.pythonhosted.org/packages/13/2f/e9d6046b0d6360c0a3f75553fdea10328e896e82069c21511542339f1d23/django_sequences-1.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ef05d6c5bdca14c4eb00bfbf702fa758", "sha256": "ef30255845a6cbb9d9da841b2e3ecbf9b2ddb84bbee4b666c5827fd716908cf5" }, "downloads": -1, "filename": "django-sequences-1.0.tar.gz", "has_sig": false, "md5_digest": "ef05d6c5bdca14c4eb00bfbf702fa758", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5454, "upload_time": "2016-01-05T20:43:31", "url": "https://files.pythonhosted.org/packages/0a/0c/067604093e826997da08e6a7ee57916aa882c9afdbcd41c8f08ea9332fbe/django-sequences-1.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "c8abf6f99d009c774ff542246ca947ea", "sha256": "39c14f61ae25b0593d576515175df118ac3004749f0173cf70e493d35dc9fdc4" }, "downloads": -1, "filename": "django_sequences-1.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c8abf6f99d009c774ff542246ca947ea", "packagetype": "bdist_wheel", "python_version": "3.4", "requires_python": null, "size": 10867, "upload_time": "2016-01-06T08:46:57", "url": "https://files.pythonhosted.org/packages/56/df/3a162850c31ae18a36c3454920abede05a2263b41d2e0e1744e2509de80f/django_sequences-1.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "ff892bc17e4bd873cc16ae2b47c13ca0", "sha256": "97c99fb6bfe6ba843608aa67ea924cb1bd5e094732ef16c6b8cb8f51f3aff021" }, "downloads": -1, "filename": "django-sequences-1.0.1.tar.gz", "has_sig": false, "md5_digest": "ff892bc17e4bd873cc16ae2b47c13ca0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5780, "upload_time": "2016-01-06T08:46:37", "url": "https://files.pythonhosted.org/packages/3e/ec/7e40c757fc65a84f4b61301265a17fe94706c1ef72d6376c8e957097c596/django-sequences-1.0.1.tar.gz" } ], "2.0": [ { "comment_text": "", "digests": { "md5": "aa60901518cc6094091412c12af3bc58", "sha256": "62aff435caad7d8c1b15ebd59c4d9b46140dd2ba9ebd3640a3e558e4396257cf" }, "downloads": -1, "filename": "django_sequences-2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "aa60901518cc6094091412c12af3bc58", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 29224, "upload_time": "2017-03-17T15:01:30", "url": "https://files.pythonhosted.org/packages/0e/cd/bc2c029a5b5bbce8ed7b505cb63c6b3892775e5daf381e96a57bcb9925b2/django_sequences-2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "abe4cf4968979d3077e8c26ea0ae6846", "sha256": "2322bbdfdc452129614bcb2e6511274868f63d4f6b37cf1cda9d1d39f623d34d" }, "downloads": -1, "filename": "django-sequences-2.0.tar.gz", "has_sig": false, "md5_digest": "abe4cf4968979d3077e8c26ea0ae6846", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11027, "upload_time": "2017-03-17T15:01:27", "url": "https://files.pythonhosted.org/packages/9c/96/86ca6128f94fdd4048e08f7848bcf082591737da5563f5a18a7547ec09b2/django-sequences-2.0.tar.gz" } ], "2.1": [ { "comment_text": "", "digests": { "md5": "06e62ae84126898fb2f532f6e5100f3f", "sha256": "c672bd84288df818e19ffede4a14b890b0e22dc6258c56b005cf902c07752295" }, "downloads": -1, "filename": "django_sequences-2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "06e62ae84126898fb2f532f6e5100f3f", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 29645, "upload_time": "2017-09-09T06:28:40", "url": "https://files.pythonhosted.org/packages/a6/70/e67b62426208d38e3d97ab737fb0c7b719cb3c5024d03383652037354729/django_sequences-2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5f2980eb4db1a4108313c3ec6e49f4cd", "sha256": "1d83e2bfeb81795bd80709a49aea7613045c8b0402955b298f1d36c2e86d85f4" }, "downloads": -1, "filename": "django-sequences-2.1.tar.gz", "has_sig": false, "md5_digest": "5f2980eb4db1a4108313c3ec6e49f4cd", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11327, "upload_time": "2017-09-09T06:28:38", "url": "https://files.pythonhosted.org/packages/b4/5a/7e11bbc72eedc0d2a7c083bf61e8f3d6095a75202964e974acb72246736e/django-sequences-2.1.tar.gz" } ], "2.2": [ { "comment_text": "", "digests": { "md5": "2f01dcc4d428d1597227fd11a5398e30", "sha256": "06103079135913ec9a718241f9e2c0d56230e8219f810da4d9790c4fa78700d9" }, "downloads": -1, "filename": "django_sequences-2.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "2f01dcc4d428d1597227fd11a5398e30", "packagetype": "bdist_wheel", "python_version": "3.6", "requires_python": null, "size": 29646, "upload_time": "2017-09-09T07:15:17", "url": "https://files.pythonhosted.org/packages/7a/2d/0c21146f8283ee56b3d920859e55be2550b2c8fb9fb8b6aa9ac2930690ea/django_sequences-2.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7c4d3aa7039e0f8199afbf9935dbc91d", "sha256": "c8d4b697c1dd044aef0aedafa4daac880d30257e4f85979695b753a6a95cb4b2" }, "downloads": -1, "filename": "django-sequences-2.2.tar.gz", "has_sig": false, "md5_digest": "7c4d3aa7039e0f8199afbf9935dbc91d", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11260, "upload_time": "2017-09-09T07:15:14", "url": "https://files.pythonhosted.org/packages/43/1a/a15e3b2d2a254166416b49577236f3c8c7f837b7611941ec23ec013db251/django-sequences-2.2.tar.gz" } ], "2.3": [ { "comment_text": "", "digests": { "md5": "d6c8acb557fe3123228ca7446648a69a", "sha256": "1058fd16db38044d8999c85530cae8f77ec329b600fd8034479ab384d3ee3e63" }, "downloads": -1, "filename": "django_sequences-2.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "d6c8acb557fe3123228ca7446648a69a", "packagetype": "bdist_wheel", "python_version": "3.7", "requires_python": null, "size": 29568, "upload_time": "2019-06-02T15:17:55", "url": "https://files.pythonhosted.org/packages/e8/36/cc2d9a0ddec6636cfa7d636f4433ca10992964f4680a686c479f4ef43370/django_sequences-2.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "585e5e29098218a90f95a265937ff987", "sha256": "15acae104db2574db849e0814930b00aa61524e1ac80bc340c09be0b15c2a1b1" }, "downloads": -1, "filename": "django-sequences-2.3.tar.gz", "has_sig": false, "md5_digest": "585e5e29098218a90f95a265937ff987", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 12336, "upload_time": "2019-06-02T15:17:53", "url": "https://files.pythonhosted.org/packages/f2/75/f021bd70ac62a6ede70766c96f464c9c6f61e02a83c70fd835bc40f6f349/django-sequences-2.3.tar.gz" } ], "2.4": [ { "comment_text": "", "digests": { "md5": "266c91ebd544010f47895bbaa7cd4c09", "sha256": "74e72e840e2d214966b2509329eabb1790c73bc71fd881ec646ed07ae3260d7d" }, "downloads": -1, "filename": "django_sequences-2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "266c91ebd544010f47895bbaa7cd4c09", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 30653, "upload_time": "2019-07-20T07:22:39", "url": "https://files.pythonhosted.org/packages/03/59/82be3d44bc95f0f369098b6d7dcb6523aa35b2ac02f3eb6c93245f870475/django_sequences-2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "93ffa0d85a444c05ae77bdebd36bf605", "sha256": "390145c012d16a78ce35fd1546128b3c949af13f5cce195362f4e987466a0b22" }, "downloads": -1, "filename": "django-sequences-2.4.tar.gz", "has_sig": false, "md5_digest": "93ffa0d85a444c05ae77bdebd36bf605", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13712, "upload_time": "2019-07-20T07:22:41", "url": "https://files.pythonhosted.org/packages/d1/04/1bec98502ead25e4dcd5b256bf11c656573da0d233367048cb543f3a25e9/django-sequences-2.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "266c91ebd544010f47895bbaa7cd4c09", "sha256": "74e72e840e2d214966b2509329eabb1790c73bc71fd881ec646ed07ae3260d7d" }, "downloads": -1, "filename": "django_sequences-2.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "266c91ebd544010f47895bbaa7cd4c09", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 30653, "upload_time": "2019-07-20T07:22:39", "url": "https://files.pythonhosted.org/packages/03/59/82be3d44bc95f0f369098b6d7dcb6523aa35b2ac02f3eb6c93245f870475/django_sequences-2.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "93ffa0d85a444c05ae77bdebd36bf605", "sha256": "390145c012d16a78ce35fd1546128b3c949af13f5cce195362f4e987466a0b22" }, "downloads": -1, "filename": "django-sequences-2.4.tar.gz", "has_sig": false, "md5_digest": "93ffa0d85a444c05ae77bdebd36bf605", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 13712, "upload_time": "2019-07-20T07:22:41", "url": "https://files.pythonhosted.org/packages/d1/04/1bec98502ead25e4dcd5b256bf11c656573da0d233367048cb543f3a25e9/django-sequences-2.4.tar.gz" } ] }