# Django Sqids
[![Github Actions](https://github.com/julianwachholz/django-sqids/workflows/test/badge.svg)](https://github.com/julianwachholz/django-sqids/actions)
[![Python Version](https://img.shields.io/pypi/pyversions/django-sqids.svg)](https://pypi.org/project/django-sqids/)
[![PyPI Package](https://img.shields.io/pypi/v/django-sqids.svg)](https://pypi.org/project/django-sqids/)
[![License](https://img.shields.io/pypi/l/django-sqids.svg)](https://github.com/julianwachholz/django-sqids/blob/main/LICENSE)
django-sqids is a simple and non-intrusive [sqids](https://sqids.org/) library for Django. It acts as a model field, but it does not touch the database or change the model.
The project was forked from [django-hashids](https://github.com/ericls/django-hashids) to provide the same functionality with the newer Sqids library.
# Features
- Proxy the internal model `pk` field without storing the value in the database.
- Allows lookups and filtering by sqid string.
- Can be used as sort key.
- Allows specifying a min_length and alphabet globally.
- Supports custom min_length, prefix, and alphabet per field.
- Supports Django REST Framework Serializers.
- Supports exact ID searches in Django Admin when field is specified in search_fields.
- Supports filtering by `__iexact`, though matching is the same as `__exact`.
- Supports other lookups: `in`, `isnull`, `gt`, `gte`, `lt`, and `lte`.
# Install
```bash
pip install django-sqids
```
`django-sqids` is tested with Django 3.2, 4.2, 5.0 and Python 3.8 - 3.12.
# Usage
Add `SqidsField` to any model
```python
from django_sqids import SqidsField
class TestModel(Model):
sqid = SqidsField(real_field_name="id")
```
`TestModel.sqid` field will proxy `TestModel.id` field but all queries will return and receive sqids strings. `TestModel.id` will work as before.
## Examples
```python
instance = TestModel.objects.create()
instance2 = TestModel.objects.create()
instance.id # 1
instance2.id # 2
# Allows access to the field
instance.sqid # '1Z'
instance2.sqid # '4x'
# Allows querying by the field
TestModel.objects.get(sqid="1Z")
TestModel.objects.filter(sqid="1Z")
TestModel.objects.filter(sqid__in=["1Z", "4x"])
TestModel.objects.filter(sqid__gt="1Z") # same as id__gt=1, would return instance 2
# Allows usage in queryset.values
TestModel.objects.values_list("sqid", flat=True) # ["1Z", "4x"]
TestModel.objects.filter(sqid__in=TestModel.objects.values("sqid"))
```
## Using with URLs
You can use sqids to identify items in your URLs by treating them as slugs.
In `urls.py`:
```python
urlpatterns = [
path("item/<slug>/", YourDetailView.as_view(), name="item-detail"),
]
```
And in your view:
```python
class YourDetailView(DetailView):
model = Item
slug_field = 'sqid'
```
## Using with Django Admin
Add the field to your ModelAdmin's `search_fields` to quickly find a record by its Sqid:
```python
class MyModelAdmin(admin.ModelAdmin):
search_fields = [
"sqid__exact",
]
```
## Config
The following attributes can be added in settings file to set default arguments of `SqidsField`:
1. `DJANGO_SQIDS_MIN_LENGTH`: default minimum length
2. `DJANGO_SQIDS_ALPHABET`: default alphabet
`SqidsField` does not require any arguments but the following arguments can be supplied to modify its behavior.
| Name | Description | Example |
| ----------------- | :-----------------------------------------------------: | ----------------------------------------------------------- |
| `real_field_name` | The proxied field name | sqid = SqidsField(real_field_name="id") |
| `sqids_instance` | The sqids instance used to encode/decode for this field | sqid = SqidsField(sqids_instance=sqids_instance) |
| `min_length` | The minimum length of sqids generated for this field | sqid = SqidsField(min_length=10) |
| `alphabet` | The alphabet used by this field to generate sqids | sqid = SqidsField(alphabet="KHE5J3L2M4N6P7Q8R9T0V1W2X3Y4Z") |
| `prefix` | The prefix used by this field to generate sqids | sqid = SqidsField(prefix="item-") |
The argument `sqids_instance` is mutually exclusive to `min_length` and `alphabet`. See [sqids-python](https://github.com/sqids/sqids-python) for more info about the arguments.
Some common Model arguments such as `verbose_name` are also supported.
## Where did the Salt go?
When the Hashids project transitioned to Sqids, [Sqids removed the "salt" parameter](https://sqids.org/faq#salt) to prevent the appearance that
it provides security or safety. In Sqids, the order of the alphabet affects the generated sqids. `django_sqids` provides a useful `shuffle_alphabet`
function that helps reintroduce the same idea as the "salt" parameter by shuffling the alphabet. This can be used to generate a unique alphabet for each
instance of `SqidsField` to prevent the same id from generating the same sqid across different instances of `SqidsField`.
The `seed` parameter is used to generate a unique ordering of alphabet for each instance of `SqidsField`. The `alphabet` parameter can be used to specify a custom alphabet.
```python
from django_sqids import SqidsField, shuffle_alphabet
class MyModel(models.Model):
# will use your configured default alphabet
sqid = SqidsField(alphabet=shuffle_alphabet(seed='randomSeed'))
class HexModel(models.Model):
sqid = SqidsField(alphabet=shuffle_alphabet(seed='randomSeed', alphabet='0123456789abcdef'))
```
Raw data
{
"_id": null,
"home_page": "https://github.com/julianwachholz/django-sqids",
"name": "django-sqids",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.8.1",
"maintainer_email": null,
"keywords": "django, sqids, sqid, hashids, hashid",
"author": "Julian Wachholz",
"author_email": "julian@wachholz.ch",
"download_url": "https://files.pythonhosted.org/packages/5e/03/f1b073130a4f6471cbac0fde08d601489ad2aa22104cb79f7f5fb19ea99e/django_sqids-0.2.1.tar.gz",
"platform": null,
"description": "# Django Sqids\n\n[![Github Actions](https://github.com/julianwachholz/django-sqids/workflows/test/badge.svg)](https://github.com/julianwachholz/django-sqids/actions)\n[![Python Version](https://img.shields.io/pypi/pyversions/django-sqids.svg)](https://pypi.org/project/django-sqids/)\n[![PyPI Package](https://img.shields.io/pypi/v/django-sqids.svg)](https://pypi.org/project/django-sqids/)\n[![License](https://img.shields.io/pypi/l/django-sqids.svg)](https://github.com/julianwachholz/django-sqids/blob/main/LICENSE)\n\ndjango-sqids is a simple and non-intrusive [sqids](https://sqids.org/) library for Django. It acts as a model field, but it does not touch the database or change the model.\n\nThe project was forked from [django-hashids](https://github.com/ericls/django-hashids) to provide the same functionality with the newer Sqids library.\n\n# Features\n\n- Proxy the internal model `pk` field without storing the value in the database.\n- Allows lookups and filtering by sqid string.\n- Can be used as sort key.\n- Allows specifying a min_length and alphabet globally.\n- Supports custom min_length, prefix, and alphabet per field.\n- Supports Django REST Framework Serializers.\n- Supports exact ID searches in Django Admin when field is specified in search_fields.\n- Supports filtering by `__iexact`, though matching is the same as `__exact`.\n- Supports other lookups: `in`, `isnull`, `gt`, `gte`, `lt`, and `lte`.\n\n# Install\n\n```bash\npip install django-sqids\n```\n\n`django-sqids` is tested with Django 3.2, 4.2, 5.0 and Python 3.8 - 3.12.\n\n# Usage\n\nAdd `SqidsField` to any model\n\n```python\nfrom django_sqids import SqidsField\n\nclass TestModel(Model):\n sqid = SqidsField(real_field_name=\"id\")\n```\n\n`TestModel.sqid` field will proxy `TestModel.id` field but all queries will return and receive sqids strings. `TestModel.id` will work as before.\n\n## Examples\n\n```python\ninstance = TestModel.objects.create()\ninstance2 = TestModel.objects.create()\ninstance.id # 1\ninstance2.id # 2\n\n# Allows access to the field\ninstance.sqid # '1Z'\ninstance2.sqid # '4x'\n\n# Allows querying by the field\nTestModel.objects.get(sqid=\"1Z\")\nTestModel.objects.filter(sqid=\"1Z\")\nTestModel.objects.filter(sqid__in=[\"1Z\", \"4x\"])\nTestModel.objects.filter(sqid__gt=\"1Z\") # same as id__gt=1, would return instance 2\n\n# Allows usage in queryset.values\nTestModel.objects.values_list(\"sqid\", flat=True) # [\"1Z\", \"4x\"]\nTestModel.objects.filter(sqid__in=TestModel.objects.values(\"sqid\"))\n```\n\n## Using with URLs\n\nYou can use sqids to identify items in your URLs by treating them as slugs.\n\nIn `urls.py`:\n\n```python\nurlpatterns = [\n path(\"item/<slug>/\", YourDetailView.as_view(), name=\"item-detail\"),\n]\n```\n\nAnd in your view:\n\n```python\nclass YourDetailView(DetailView):\n model = Item\n slug_field = 'sqid'\n```\n\n## Using with Django Admin\n\nAdd the field to your ModelAdmin's `search_fields` to quickly find a record by its Sqid:\n\n```python\nclass MyModelAdmin(admin.ModelAdmin):\n search_fields = [\n \"sqid__exact\",\n ]\n```\n\n## Config\n\nThe following attributes can be added in settings file to set default arguments of `SqidsField`:\n\n1. `DJANGO_SQIDS_MIN_LENGTH`: default minimum length\n2. `DJANGO_SQIDS_ALPHABET`: default alphabet\n\n`SqidsField` does not require any arguments but the following arguments can be supplied to modify its behavior.\n\n| Name | Description | Example |\n| ----------------- | :-----------------------------------------------------: | ----------------------------------------------------------- |\n| `real_field_name` | The proxied field name | sqid = SqidsField(real_field_name=\"id\") |\n| `sqids_instance` | The sqids instance used to encode/decode for this field | sqid = SqidsField(sqids_instance=sqids_instance) |\n| `min_length` | The minimum length of sqids generated for this field | sqid = SqidsField(min_length=10) |\n| `alphabet` | The alphabet used by this field to generate sqids | sqid = SqidsField(alphabet=\"KHE5J3L2M4N6P7Q8R9T0V1W2X3Y4Z\") |\n| `prefix` | The prefix used by this field to generate sqids | sqid = SqidsField(prefix=\"item-\") |\n\nThe argument `sqids_instance` is mutually exclusive to `min_length` and `alphabet`. See [sqids-python](https://github.com/sqids/sqids-python) for more info about the arguments.\n\nSome common Model arguments such as `verbose_name` are also supported.\n\n## Where did the Salt go?\n\nWhen the Hashids project transitioned to Sqids, [Sqids removed the \"salt\" parameter](https://sqids.org/faq#salt) to prevent the appearance that\nit provides security or safety. In Sqids, the order of the alphabet affects the generated sqids. `django_sqids` provides a useful `shuffle_alphabet` \nfunction that helps reintroduce the same idea as the \"salt\" parameter by shuffling the alphabet. This can be used to generate a unique alphabet for each\ninstance of `SqidsField` to prevent the same id from generating the same sqid across different instances of `SqidsField`.\n\nThe `seed` parameter is used to generate a unique ordering of alphabet for each instance of `SqidsField`. The `alphabet` parameter can be used to specify a custom alphabet.\n\n```python\nfrom django_sqids import SqidsField, shuffle_alphabet\n\nclass MyModel(models.Model):\n # will use your configured default alphabet\n sqid = SqidsField(alphabet=shuffle_alphabet(seed='randomSeed'))\n\nclass HexModel(models.Model):\n sqid = SqidsField(alphabet=shuffle_alphabet(seed='randomSeed', alphabet='0123456789abcdef'))\n\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Non-intrusive sqids library for Django",
"version": "0.2.1",
"project_urls": {
"Homepage": "https://github.com/julianwachholz/django-sqids",
"Repository": "https://github.com/julianwachholz/django-sqids"
},
"split_keywords": [
"django",
" sqids",
" sqid",
" hashids",
" hashid"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "1e86a4a639f1fea5990a0b3c4b712e11427633c0b30f7424ab06c6ff618c4098",
"md5": "429eb5c556f1e5ca6bd01bfa2330b7a8",
"sha256": "d641b19f21c1190abb1d3fafbeb3e469c94935f8eb6a489360a0df8f3d1bcc25"
},
"downloads": -1,
"filename": "django_sqids-0.2.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "429eb5c556f1e5ca6bd01bfa2330b7a8",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4,>=3.8.1",
"size": 6310,
"upload_time": "2024-10-11T06:18:50",
"upload_time_iso_8601": "2024-10-11T06:18:50.610782Z",
"url": "https://files.pythonhosted.org/packages/1e/86/a4a639f1fea5990a0b3c4b712e11427633c0b30f7424ab06c6ff618c4098/django_sqids-0.2.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "5e03f1b073130a4f6471cbac0fde08d601489ad2aa22104cb79f7f5fb19ea99e",
"md5": "521aae935e2498373a92ba65c9ba284b",
"sha256": "97d0f4b3ad4348c69a4ccc005bfefdd68e45b41d3645d34d5393cea1c916f5de"
},
"downloads": -1,
"filename": "django_sqids-0.2.1.tar.gz",
"has_sig": false,
"md5_digest": "521aae935e2498373a92ba65c9ba284b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.8.1",
"size": 5621,
"upload_time": "2024-10-11T06:18:52",
"upload_time_iso_8601": "2024-10-11T06:18:52.067012Z",
"url": "https://files.pythonhosted.org/packages/5e/03/f1b073130a4f6471cbac0fde08d601489ad2aa22104cb79f7f5fb19ea99e/django_sqids-0.2.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-11 06:18:52",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "julianwachholz",
"github_project": "django-sqids",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-sqids"
}