0

Currently the top answer for How does a Django UUIDField generate a UUID in Postgresql? says

When you use UUIDField as a primary key in Django, it doesn't generate a UUID one for you, you generate it yourself before you save the object

But I think it should be possible to hack a solution that allows for DB-based UUID generation.

Once you have installed uuid-ossp extension in postgres

CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

I think it should work more or less like an AutoField.

If a raw sql has been used for the table creation

CREATE TABLE example(
   id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
);

Then raw insert will return a new random UUID as an id field.

How would one go about creating a custom Field so this raw solution works with Django ORM?

Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44
  • 1
    Why do you feel this step is necessary, what do you think you will gain by transferring UUID generation on database – iklinac Aug 04 '20 at 13:10
  • There are cases when I need to check if object is new. So far I did `self.pk is None`. I think `self._state.adding` is not 100% reliable. Another option is `FieldTracker` from `model-utils` but it comes with a performance hit and using a proxy model only for that is an overkill. – Tom Wojcik Aug 04 '20 at 13:18
  • you can omit default from your UUID primary and set it inside of save method instead, this way self.pk wont be set for new records prior to entering into save method – iklinac Aug 04 '20 at 13:27
  • As I'm gonna put that in a Mixin I will have to make sure MRO is in the proper order but yes, that's a neat trick. I'll do that, thanks! – Tom Wojcik Aug 04 '20 at 13:30
  • 1
    Furthermore you can specify pre_save hook to generate uuid automatically just a moment before you actually save. See here https://docs.djangoproject.com/en/3.0/ref/signals/ It sounds much simplier than adding a new field with custom interface to db. – Yuri Nudelman Aug 04 '20 at 13:30
  • I'm not a fan of signals but yes, that's also a clean solution. Will consider that, thanks! – Tom Wojcik Aug 04 '20 at 13:33

1 Answers1

1

I just run into the solution for this question I asked a year ago. Django provides you with RandomUUID which calls gen_random_uuid in PostgreSQL.

Example usage:

from django.contrib.postgres.functions import RandomUUID

class MyModel(models.Model):
    id = models.UUIDField(primary_key=True, default=RandomUUID)

Where RandomUUID is

class RandomUUID(Func):
    template = 'GEN_RANDOM_UUID()'
    output_field = UUIDField()

For version below 13 PostgreSQL docs mention that calling gen_random_uuid

Returns a version 4 (random) UUID. (Obsolete, this function is now also included in core PostgreSQL.)

It's obsolete as "obsolete in pgcrypto" extension.

In PostgreSQL docs for version 13 and above you can find this function being mentioned under Chapter 9. Functions and Operators section.

This function returns a version 4 (random) UUID. This is the most commonly used type of UUID and is appropriate for most applications.

Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44