Cannot cast type integer to uuid
Asked Answered
T

1

13

I tried to run python3 manage.py migrate, but i got this error:

  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/django /db/backends/utils.py", line 84, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: cannot cast type integer to uuid
LINE 1: ...BLE "core_post" ALTER COLUMN "id" TYPE uuid USING "id"::uuid

I'm using PostgreSQL

My models.py: Link to pastebin

I hope you will help me)

Thank you!

Taffrail answered 12/10, 2020 at 14:10 Comment(5)
Imagine that the column contains a number 5, how would you convert that to a uuid?Agraphia
@WillemVanOnsem a UUID is 128-bit int, all zeroes ending in a 5. However, this likely conflicts with namespaces reserved for different UUID types at some point.Arabic
@Melvyn: well the way it is represented is a 128 bit quantity yes. But for example one does not use a uuid to represent an amount of items, especially since a uuid should is a universally unique identifier. The "first generation" of prgramming languages of course did not make that distinction, but I think fourth generation programming concepts and beyond likely reject that idea.Agraphia
@WillemVanOnsem Neither does it here: he's changing the primary key from serial number to uuid. Now this won't work, cause postgres won't allow it, as specific namespaces are defined for specific uuid types (1 through 5), but in theory, it wouldn't be a problem. And don't get hung up on the Universally Unique. It's not guaranteed, just improbable.Arabic
@Melvyn: well it would. Since universally unique means that it is quasi impossible for colissions. But if you would transform two primary keys to integers, the likelihood of a clash is (near) absolute. So these are basically two words, where in practial sense an uuid is represented as a 128 bit number, but conceptually two two are different worlds. This is basically what the third generation brough to the table: a taxonomy. As in, meaning is more than data: it is data with context.Agraphia
A
39

So, basically you started the model without an explicit primary key. So you got a free AutoField and now want them to be UUID's.

As you can see, Postgres (or any db I know of) doesn't allow changing integers to UUIDs. So you need do a few migrations to get the state you want to:

First add the uuid field as a normal field with a different name:

import uuid
from django.db import models

class MyModel(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, unique=True)

Run makemigrations and migrate.

Now make it primary key:

class MyModel(models.Model):
    uuid = models.UUIDField(default=uuid.uuid4, primary_key=True)

This should generate a migration that removes the id field and makes uuid primary key (makemigrations and migrate again).

And finally (if you still want to):

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

Honestly, I don't know if this goes OK, you may have to adjust the generated migration. In either case, you've should now be where you want to be.

Arabic answered 12/10, 2020 at 14:50 Comment(3)
Hi, I've multiple objects in my model that I wish to migrate to uuid, now when I'm creating the "uuid" field in the first step, the unique =True condition fails as I get the same value for all the objects. How can I iterate over the objects and generate a unique uuid id for each of them?Stripling
Found a solution, https://mcmap.net/q/903300/-how-to-make-uuid-field-default-when-there-39-s-already-id-field, can try this!Stripling
You did default=uuid.uuid4() not default=uuid.uuid4.Arabic

© 2022 - 2024 — McMap. All rights reserved.