Registry / database / django-sequences

django-sequences

JSON →
library3.0pypypi✓ verified 86d ago

django-sequences is a Python library for Django that provides a reliable way to generate gapless sequences of integer values. Unlike Django's default auto-incrementing primary keys, which can have gaps due to rolled-back transactions, this library ensures sequential integrity. It is currently at version 3.0, actively maintained, and compatible with modern Django versions (3.2 and up).

pip install django-sequences
INSTALL
IMPORT
SIG · DJANGO-SEQUENCES
D
django-sequences
databasepythonv3.0
Install
3.5s avg
Import
265ms
Disk
66MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v3.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.276s · 66.6MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 3.5s · import 0.253s · 67MB
66MB installed
● package 66MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

get_next_value
from sequences import get_next_value
from django_sequences import get_next_value
The top-level package name is 'sequences', not 'django_sequences'.
Sequence
from sequences import Sequence
Provides an object-oriented API for sequence generation.
SequencesConfig
INSTALLED_APPS = [..., 'sequences.apps.SequencesConfig', ...]
Required to register the application in Django settings.

To generate a gapless sequence, ensure that `get_next_value()` and the subsequent database save operation occur within the same atomic transaction. The library provides `get_next_value()` for a functional approach and a `Sequence` class for an object-oriented API. Remember to add `sequences.apps.SequencesConfig` to your `INSTALLED_APPS` and run migrations.

import os from django.db import transaction from sequences import get_next_value # Assume 'Invoice' is a Django model with an 'number' field # from invoices.models import Invoice # For demonstration, we'll mock a model and save operation class MockInvoice: _instances = [] def __init__(self, number): self.number = number print(f"Created MockInvoice with number: {self.number}") MockInvoice._instances.append(self) def create_invoice_with_sequence(sequence_name='invoice_numbers'): try: with transaction.atomic(): next_invoice_number = get_next_value(sequence_name) # Replace with your actual model creation: # Invoice.objects.create(number=next_invoice_number) MockInvoice(number=next_invoice_number) print(f"Successfully committed invoice with number: {next_invoice_number}") except Exception as e: print(f"Transaction failed: {e}") # Example usage: create_invoice_with_sequence('orders') create_invoice_with_sequence('orders') create_invoice_with_sequence('shipments', initial_value=1000) create_invoice_with_sequence('shipments')
Debug
Known issues
gotchaFor django-sequences to guarantee gapless values, `get_next_value()` and the corresponding model save operation MUST be executed within the same database transaction. If the transaction is committed, the value is consumed; otherwise, if the transaction rolls back, the value is not consumed by the user's model but the sequence counter is still incremented internally.
fix
Always wrap your `get_next_value()` call and model creation/update in `django.db.transaction.atomic()`.
affects: All versions
gotchaIf a transaction involving `get_next_value()` is rolled back (e.g., due to an error in your code after retrieving the value but before committing), the internal sequence counter for `django-sequences` itself is NOT rolled back for performance reasons. This means there will be a 'gap' in the sequence numbers generated by `django-sequences` if you inspect its internal table, even though your application's committed records remain gapless.
fix
This is expected behavior and a trade-off for performance. Design your application to handle occasional internal sequence gaps if auditing the `sequences` table directly.
affects: All versions
gotchaDatabase transactions that call `get_next_value()` for a given sequence are serialized. This means concurrent calls for the *same* sequence will block, potentially impacting performance. Keep transactions involving `get_next_value()` as short as possible.
fix
Minimize the amount of work performed within the `transaction.atomic()` block that calls `get_next_value()`. Consider using `nowait=True` on `get_next_value()` for non-blocking behavior, though this might raise exceptions on contention.
affects: All versions
breakingThe `read uncommitted` database isolation level is NOT supported and will lead to gaps and incorrect behavior. The `repeatable read` level is supported but requires application-level handling of serialization failures and retries.
fix
Use the `read committed` isolation level for optimal compatibility and guarantees. If using `repeatable read`, implement retry logic for transactions that encounter serialization errors.
affects: All versions
Errors
Common errors & fixes
IntegrityError: duplicate key value violates unique constraint
`get_next_value` was called, but the model saving the value was not wrapped in an atomic transaction or the transaction failed to commit, leading to a duplicate value being attempted later.
fix
Ensure all calls to `get_next_value()` and the subsequent `model.save()` are within a `with transaction.atomic():` block.
Application is slow when multiple users/processes try to generate sequence numbers simultaneously.
Access to `get_next_value()` for a specific sequence is serialized at the database level to ensure gapless numbers. Long-running transactions or very high contention can lead to performance bottlenecks.
fix
Optimize the code within the `transaction.atomic()` block to be as fast as possible. If extreme concurrency is needed and occasional non-sequential IDs are acceptable, consider alternative ID generation strategies or sharding sequences across different names.
Gaps appear in generated sequence numbers in my application's records.
This typically happens if the `get_next_value()` call and the record creation/update are not within the same atomic transaction, or if a transaction committed a value, but later records were inserted using a different mechanism or without using the sequence correctly.
fix
Verify that `django.db.transaction.atomic()` strictly wraps both the `get_next_value()` call and the database `create()` or `save()` for the record that uses the generated number.
Upgrade
Version history
3.0latest on PyPI · released Jan 31, 2024
Audit
Dependencies
DjangorequiredCore framework dependency; tested with Django 3.2 (LTS), 4.0, 4.1, 4.2 (LTS), 5.0, 5.1, 5.2 (LTS), and 6.0.
Agent activity
6 hits · last 30 days
node
6
Resources