Fwd: Filtering by custom UUIDField got broken with Django 3.2 upgrade

248 views
Skip to first unread message

Milán Boleradszki

unread,
May 4, 2022, 11:14:02 AM5/4/22
to django...@googlegroups.com
Hello Django users,

I've recently upgraded the Django version from 2.2 to 3.2 in a project at work. In this project, we've been using a custom version of UUIDField since version 1.x without issues. The purpose of this field is to persist the full UUIDs with dashes into the database (MySQL char(36)).

import uuid

from django.db import models


class UUIDField(models.UUIDField):
    """
    Overrides Django UUIDField to store full UUID's including dashes.
    """
    def __init__(self, verbose_name=None, **kwargs):
        super().__init__(verbose_name, **kwargs)
        self.max_length = 36

    def get_internal_type(self):
        return "CharField"

    def get_db_prep_value(self, value, connection, prepared=False):
        if value is None:
            return None
        if not isinstance(value, uuid.UUID):
            try:
                value = uuid.UUID(value)
            except AttributeError:
                raise TypeError(self.error_messages['invalid'] % {'value': value})

        if connection.features.has_native_uuid_field:
            return value
        return str(value)

Now the problem introduced with 3.2 is that filtering by this field doesn't work properly. If I try to filter by a full UUID (with or without dashes) it returns an empty QuerySet. If I provide only one part of the UUID (i.e. one group of characters between the dashes) it works just fine.

Python 3.6.9 (default, Mar 15 2022, 13:55:28)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from foobar.foo.models import Foo
>>>
>>> Foo.objects.all()
<QuerySet [<Foo: Foo object (34c46fe8-caf0-11ec-bdb9-482ae362a4c0)>]>
>>>
>>> Foo.objects.filter(id__icontains='34c46fe8-caf0-11ec-bdb9-482ae362a4c0')
<QuerySet []>
>>>
>>> Foo.objects.filter(id__icontains='34c46fe8-')
<QuerySet [<Foo: Foo object (34c46fe8-caf0-11ec-bdb9-482ae362a4c0)>]>
>>>
>>> Foo.objects.filter(id__icontains='34c46fe8-c')
<QuerySet []>
>>>
Here's a little Github Gist where I uploaded a simplified model.py and admin.py along with the UUIDField. This is what I used above in the python shell. Any help would be appreciated, I couldn't figure out how to fix it.

(PS: I also raised this in StackOverflow just in case you came across with it.)

Cheers,
Milan


Jason

unread,
May 5, 2022, 7:27:02 AM5/5/22
to Django users
when you print the query executed, what is the difference between a working query and the current one?

Jason

unread,
May 5, 2022, 7:29:07 AM5/5/22
to Django users
and curious why the change in this behavior vs using the db's native uuid type directly

Michael Powell

unread,
May 5, 2022, 9:08:29 AM5/5/22
to Django users
AFAIK, 'dashes' in a character based persisted UUID is divergent behavior. UUID are 128 bits wide, apportioned by nibble into a character field, 32 at most. So... The migration is yours to correct. Good luck, good hunting, HTH.

On Wednesday, May 4, 2022 at 11:14:02 AM UTC-4 bmila...@gmail.com wrote:
Reply all
Reply to author
Forward
0 new messages