#32577: Add support for `UUIDAutoField` `DEFAULT_AUTO_FIELD`
-------------------------------------+-------------------------------------
Reporter: Tomasz Wójcik | Owner: (none)
Type: New feature | Status: new
Component: Database layer | Version: dev
(models, ORM) |
Severity: Normal | Resolution:
Keywords: uuid autofield | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Ekin Ertaç):
I've implemented UUIDAutoField support for DEFAULT_AUTO_FIELD, following
the approach outlined by [comment:11 Nick Pope]. Here's what I did:
The main change was updating the validation so DEFAULT_AUTO_FIELD accepts
any field that subclasses AutoFieldMixin, not just AutoField. This opens
up the possibility for non-integer auto-generated primary keys like UUIDs,
which addresses the original request.
I updated the validation in `django/db/models/options.py` to check for
AutoFieldMixin instead of AutoField, and updated the error messages
accordingly.
Then I created the UUIDAutoField class in
`django/db/models/fields/__init__.py`, following the structure [comment:11
Nick Pope] suggested. It inherits from both AutoFieldMixin and UUIDField,
and automatically sets `db_default=UUID4()` if you don't provide one. This
ensures UUIDs are generated by the database rather than Python, which is
important for auto-generated fields. I also made sure it handles
deconstruction properly by removing the auto-set db_default.
I ran into a circular import issue when trying to use isinstance checks
for AutoFieldMixin, so I replaced those with `field.db_returning` checks
in `django/forms/models.py` and `django/db/models/query.py`. This actually
works better since it identifies any auto-generated field, not just
specific types. As [comment:11 Nick Pope] mentioned, using a flag like
this is preferable to isinstance checks anyway.
One thing I had to fix was adding "UUIDAutoField": "uuid" to PostgreSQL's
data_types dictionary in `django/db/backends/postgresql/base.py`. Without
this, the schema editor didn't know how to create the UUID column type, so
tables were being created without the primary key column. That was a fun
debugging session.
I added tests - one unit test to verify you can set UUIDAutoField as
DEFAULT_AUTO_FIELD, and a database test on PostgreSQL that actually
creates objects and verifies the UUIDs are generated by the database
(using GEN_RANDOM_UUID()). Everything works as expected.
The field works on databases that support the UUID4() function -
PostgreSQL (tested), MySQL 8.0.13+/MariaDB 11.7+, and Oracle 23ai/26ai+.
SQLite doesn't support function-based db_default in CREATE TABLE, so it
won't work there, but that's expected. As noted in the discussion, this is
limited to databases that have a function to generate UUIDs.
Regarding [comment:37 Simon Charette]'s question about UUIDv4 vs UUIDv7 -
I went with UUIDv4 since that's what the UUID4() database function
provides, and it's what was discussed in the ticket. Users can always
create their own field with UUID7() if they prefer. The important part is
that the infrastructure is now in place to support non-integer auto
fields.
Now users can just set `DEFAULT_AUTO_FIELD =
"django.db.models.UUIDAutoField"` and all their models will automatically
get UUID primary keys with database-generated UUIDs. This should address
the use case mentioned in the original ticket description.
The implementation is done and tested. Documentation would be nice to add
next, but the code is ready to go.
[https://github.com/django/django/pull/20508]
--
Ticket URL: <https://code.djangoproject.com/ticket/32577#comment:44>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/0107019b9a2ea924-d4b8902e-2ba4-402a-b527-9b64ab83860d-000000%40eu-central-1.amazonses.com.