72

I am trying to get unique IDs for my Django objects. In Django 1.8 they have the UUIDField. I am unsure how to use this field in order to generate unique IDs for each object in my model.

Here is what I have for the UUIDField

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

class Person(models.Model):
    ...
    unique_id = MyUUIDModel()

I can reproduce the id for the UUID model, but everytime I do I get the exact same id. For Example:

person = Person.objects.get(some_field = some_thing)
id = person.unique_id.id

id then gives me the same id every time. What is wrong, how do I fix this?

Chad Crowe
  • 1,260
  • 1
  • 16
  • 21

7 Answers7

130

I'm not sure why you've created a UUID model. You can add the uuid field directly to the Person model.

class Person(models.Model):
    unique_id = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)

Each person should then have a unique id. If you wanted the uuid to be the primary key, you would do:

class Person(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

Your current code hasn't added a field to the person. It has created a MyUUIDModel instance when you do MyUUIDModel(), and saved it as a class attribute. It doesn't make sense to do that, the MyUUIDModel will be created each time the models.py loads. If you really wanted to use the MyUUIDModel, you could use a ForeignKey. Then each person would link to a different MyUUIDModel instance.

class Person(models.Model):
    ...
    unique_id = models.ForeignKey(MyUUIDModel, unique=True)

However, as I said earlier, the easiest approach is to add the UUID field directly to the person.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
14

You need to use the class you created as a subclass when declaring your Person model like this:

import uuid
from django.db import models

class MyUUIDModel(models.Model):
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

class Person(MyUUIDModel):
  ...

This way Person becomes a subclass of MyUUIDModel and will inherit its id field definition.

Sylvestre
  • 143
  • 1
  • 6
  • 2
    this seems to capture the OP's intent, I think? – simon Sep 07 '17 at 19:29
  • 10
    You should make `MyUUIDModel` abstract to avoid creating a table for it. If you don't, all classes that subclass `MyUUIDModel` will share a common table with their IDs. See https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes – beruic Mar 15 '19 at 10:31
13

EDIT: Actually I was wrong. It's not possible yet to implement it as DEFAULT_AUTO_FIELD as it has to inherit from IntegerField. Here's the ticket in the django project with feature request to make it possible. Once it's resolved I'll update my answer.


As of Django 3.2, if you want to use uuid as a pk for all your models on a project-wide level, you don't need a generic abstract model anymore. Just define DEFAULT_AUTO_FIELD setting

default value

DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'

so something like this should work

DEFAULT_AUTO_FIELD = 'django.db.models.UUIDField'

Or even better, create your own field.

DEFAULT_AUTO_FIELD = 'project.common.models.CustomUUIDField'

Where you also define uuid type etc.

As seen in the docs, it can also be applied on an app level.

class MyAppConfig(AppConfig):
    default_auto_field = 'project.common.models.CustomUUIDField'
Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44
  • 3
    In 3.2, it says `Primary key 'django.db.models.UUIDField' referred by DEFAULT_AUTO_FIELD must subclass AutoField.` – Anuj TBE Apr 22 '21 at 16:03
  • 1
    Yes, that's exactly what I wrote in the ticket I added as an edit to this message a month ago. – Tom Wojcik Apr 22 '21 at 19:12
11

You can directly add the id field as a UUIDField in the Person model. There is no need for a separate MyUUIDModel.

I think you have confused it with the MyUUIDModel used in the UUIDField example where the id is a UUIDField. You can just use the below code and it will use UUIDs for id.

import uuid
from django.db import models

class Person(models.Model):
    ...
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) 
Rahul Gupta
  • 46,769
  • 10
  • 112
  • 126
2

To use UUID in Django for a new model see Django Docs.

However, if you want to use it for the existing model (with unique=True) having data corresponding to it, you will not be able to do it directly by the above documentation. It will create migration errors. To do it without losing the data follow all the steps carefully of this Django Documentation.

Jatin Goyal
  • 487
  • 1
  • 4
  • 11
1

in model import uuid:

import uuid

in class model use:

class Article(TimeStampedModel):
    uuid = models.UUIDField(editable=False, default=uuid.uuid4, unique=True)
    user = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='articles', null=True)
    categories = models.ManyToManyField(ArticleCategory, blank=True)
    title = models.CharField(max_length=500, null=True, blank=True)
    body = RichTextUploadingField(config_name='portal_lobar_config')
    image = models.ImageField(upload_to='article_images/', null=True, blank=True)
    headline = models.BooleanField(default=True)
    tags = models.ManyToManyField(ArticleTag, blank=True)
    slug = AutoSlugField(max_length=500, populate_from='title', unique_with='created__month', null=True)
    published = models.BooleanField(default=False)
    published_at = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['-created']
Ayush Gupta
  • 1,166
  • 2
  • 9
  • 25
Gata
  • 361
  • 3
  • 4
-3

You can use the UUIDField in Django to generate unique IDs for each object in your model. The UUIDField is a special field to store universally unique identifiers. It uses Python’s UUID class. UUID, Universal Unique Identifier, is a python library that helps in generating random objects of 128 bits as ids. It provides the uniqueness as it generates ids on the basis of time, Computer hardware (MAC etc.). Universally unique identifiers are a good alternative to AutoField for primary_key. The database will not generate the UUID for you, so it is recommended to use default. Here is an example of how you can use the UUIDField:

import uuid
from django.db import models

class MyUUIDModel(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

class Person(models.Model):
    ...
    unique_id = models.ForeignKey(MyUUIDModel)

This should work for you. If you still face issues with generating unique IDs every time you create an object, you can try using uuid.uuid1() instead of uuid.uuid4(). The uuid1() function generates a UUID from the host ID, sequence number, and the current time.

  • 1
    Welcome to Stack Overflow! This answer, along with the other two you posted today, appears likely to have been written (entirely or partially) by AI (e.g., ChatGPT). Please be aware that [posting of AI-generated content is banned here](//meta.stackoverflow.com/q/421831). If you used an AI tool to assist with any answer, I would encourage you to delete it. – NotTheDr01ds Jun 03 '23 at 16:41
  • **Readers should review this answer carefully and critically, as AI-generated information often contains fundamental errors and misinformation.** If you observe quality issues and/or have reason to believe that this answer was generated by AI, please leave feedback accordingly. The moderation team can use your help to identify quality issues. – NotTheDr01ds Jun 03 '23 at 16:42
  • In my quick review, it looks like this doesn't answer the question that was asked, as the OP was already using UUIDField, which is what you (or the AI you used) seem to recommend as the solution. This is a common GPT problem, which demonstrates why AI isn't allowed here. – NotTheDr01ds Jun 03 '23 at 16:44
  • This answer looks like it was generated by an AI (like ChatGPT), not by an actual human being. You should be aware that [posting AI-generated output is officially **BANNED** on Stack Overflow](https://meta.stackoverflow.com/q/421831). If this answer was indeed generated by an AI, then I strongly suggest you delete it before you get yourself into even bigger trouble: **WE TAKE PLAGIARISM SERIOUSLY HERE.** Please read: [Why posting GPT and ChatGPT generated answers is not currently acceptable](https://stackoverflow.com/help/gpt-policy). – tchrist Jul 07 '23 at 02:06