Metadata-Version: 2.4
Name: python-ulid-django
Version: 1.6.0
Summary: ULID (Universally Unique Lexicographically Sortable Identifier) support for Django.
Keywords: django,ulid,identifier,primary-key,uuid
Author: Xdynix
Author-email: Xdynix <Lizard.rar@gmail.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Framework :: Django :: 6.1
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Dist: django>=5.2.0,<7.0.0
Requires-Dist: python-ulid>=3.0.0,<5.0.0
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/Xdynix/python-ulid-django
Project-URL: Repository, https://github.com/Xdynix/python-ulid-django
Project-URL: Issues, https://github.com/Xdynix/python-ulid-django/issues
Description-Content-Type: text/markdown

# python-ulid-django

[ULID (Universally Unique Lexicographically Sortable Identifier)][ulid-spec] support for
Django.

This package uses the ULID type implemented by [`python-ulid`][python-ulid].

> This package is heavily inspired by [`django-ulid`][django-ulid]. The reason I'm
> reinventing the wheel is that I want to use [`python-ulid`][python-ulid]'s
> ULID implementation.

## Requirements

Python 3.12+ and Django 5.2+.

## Usage

### Installation

```shell
pip install python-ulid-django
```

### Model Field

You can then add `ULIDField` to your Django model just like other fields.

Example:

```python
from django.contrib.auth.models import AbstractUser
from ulid import ULID
from ulid_django.models import ULIDField


class User(AbstractUser):
    id = ULIDField(primary_key=True, default=ULID, editable=False)
```

### Form Field

`ULIDField` supplies a matching form field automatically, so a `ModelForm` needs
no extra wiring. Use it directly when building a plain form:

```python
from django import forms
from ulid_django.forms import ULIDField


class LookupForm(forms.Form):
    item_id = ULIDField()
```

It cleans to a `ULID` and accepts three input widths: the 26-character canonical
representation, a 32-character hex string, and a 36-character UUID string.

### URL Converter

A URL converter is also provided.

```python
from django.urls import path, register_converter
from ulid import ULID
from ulid_django.converters import ULIDConverter


def user_detail_view(request, user_id):
    assert isinstance(user_id, ULID)
    ...


register_converter(ULIDConverter, "ulid")

urlpatterns = [
    path("user/<ulid:user_id>/", user_detail_view),
    ...,
]
```

## Development

Prerequisite: [uv](https://docs.astral.sh/uv/) and [just](https://just.systems/)

Environment setup: `just dev-setup`

Run linters: `just lint`

Test: `just test`

Test against every supported Python version: `just test-all`

[ulid-spec]: https://github.com/ulid/spec

[python-ulid]: https://github.com/mdomke/python-ulid

[django-ulid]: https://github.com/ahawker/django-ulid
