#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.

Reply via email to