#30526 closed Bug (invalid)
migration to UUID id field doesn't properly convert integers (SQLite).
Reported by: | Martin Baker | Owned by: | nobody |
---|---|---|---|
Component: | Migrations | Version: | dev |
Severity: | Normal | Keywords: | UUID |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
This may be present in other DBs, but I've noticed it with SQLite under Django 2.2.1.
Steps to reproduce:
- Start a model with an implicit integer id, and create and run the migration:
from django.db import models class Something(models.Model): name = models.CharField(max_length=32)
- Then create one instance via the shell (
python manage.py shell
):
from uuidbug.models import Something s = Something(name="One") s.save()
In the DB it looks like this (can use python manage.py dbshell
):
sqlite> .headers on sqlite> select * from uuiditem_something; name|id One|1
- Edit the model to use UUIDs:
import uuid from django.db import models class Something(models.Model): name = models.CharField(max_length=32) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
- After creating and running the migration, add another instance:
from uuidbug.models import Something s = Something(name="After UUID-ization") s.save()
DB now looks like this:
sqlite> select * from uuidbug_something; name|id One|1 After UUID-ization|693e1942d7d142289bb9fb3664f2c11a
Note that the id for the first instance has not been converted to a UUID properly. If you try to access the objects, you get an error:
>>> Something.objects.all() Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/manager.py", line 82, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/query.py", line 653, in first for obj in (self if self.ordered else self.order_by('pk'))[:1]: File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/query.py", line 274, in __iter__ self._fetch_all() File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/query.py", line 1242, in _fetch_all self._result_cache = list(self._iterable_class(self)) File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/query.py", line 72, in __iter__ for row in compiler.results_iter(results): File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/models/sql/compiler.py", line 1044, in apply_converters value = converter(value, expression, connection) File "/Users/martin/Connery/opencc-backend/venv/lib/python3.7/site-packages/django/db/backends/sqlite3/operations.py", line 294, in convert_uuidfield_value value = uuid.UUID(value) File "/usr/local/Cellar/python/3.7.3/Frameworks/Python.framework/Versions/3.7/lib/python3.7/uuid.py", line 160, in __init__ raise ValueError('badly formed hexadecimal UUID string') ValueError: badly formed hexadecimal UUID string
Change History (3)
comment:1 by , 5 years ago
Description: | modified (diff) |
---|
comment:2 by , 5 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Summary: | migration to UUID id field doesn't properly convert integers (SQLite) → migration to UUID id field doesn't properly convert integers (SQLite). |
Version: | 2.2 → master |
comment:3 by , 5 years ago
I guess to me this just seems like something Django should be able to automagically take care of. This seems like a semi-frequent use case: I made some objects, oh oops I want them to be non-sequential / UUID-y.
Thanks for this report, however changing column data type is always a sensitive operation and you need to be aware of database caveats. SQLite doesn't have a native
UUID
data type, so Django handles it as achar(32)
. Altering data type frominteger
tochar
is possible with auto-conversion that's why you didn't get any issue when running this migration. I don't think that there is much that Django can do here.To fix existing data you can add custom data migration and use Python's
uuid.UUID(int=existing_pk)
to convert data fromint
toUUID
.