nshafer / django-hashid-field

Django Model Field that uses Hashids to obscure the value
MIT License
370 stars 40 forks source link

Using get_object_or_404 with django-hashid-field #64

Closed thomascenni closed 3 years ago

thomascenni commented 3 years ago

Hi all, I am using the well known shortcut https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/#get-object-or-404 to check if the object exist with the given hashid. This is a part of my model:

class QRCode(models.Model):
    serial_id = BigHashidAutoField(primary_key=True, min_length=24)

For example:

Now the problem is that if I query the DB with the serial_id in lower case, "gv961an2lry8mwr4ex8ya5mj", the get_object_or_404() returns me the object. ``qr = get_object_or_404(QRCode, pk=serial_id)`` Is it something related to django_hashid_field or to standard Django ? Thanks for the support.
nshafer commented 3 years ago

Since you're using the default alphabet, which includes lower and upper case characters, the case is significant, so you should not be able to get an object with a lowercase version of the hashid, that is correct. get_object_or_404() is just a basic wrapper around QRCode.objects.get(pk="abcd") in a try/catch, so it's not doing anything special that would cause this.

That said, I am not able to duplicate what you're describing.

# in my models.py
class QRCode(models.Model):
    serial_id = BigHashidAutoField(primary_key=True, min_length=24)

$ ./manage.py shell_plus --print-sql
In [1]: QRCode._meta.get_fields()                                                                             
Out[1]: (<hashid_field.field.BigHashidAutoField: serial_id>)

In [2]: qr = QRCode.objects.create()                                                                          
INSERT INTO "library_qrcode" ("serial_id")
VALUES (NULL)

Execution time: 0.004069s [Database: default]

In [3]: qr.serial_id                                                                                          
Out[3]: Hashid(1): 8x4Xryk7Ba9p1AGJQ1REeKL0

In [4]: qr.pk                                                                                                 
Out[4]: Hashid(1): 8x4Xryk7Ba9p1AGJQ1REeKL0

In [5]: from django.shortcuts import get_object_or_404                                                        

In [6]: get_object_or_404(QRCode, pk=str(qr.serial_id))                                                       
SELECT "library_qrcode"."serial_id"
  FROM "library_qrcode"
 WHERE "library_qrcode"."serial_id" = 1
 LIMIT 21

Execution time: 0.000497s [Database: default]
Out[6]: <QRCode: QRCode object (8x4Xryk7Ba9p1AGJQ1REeKL0)>

In [7]: get_object_or_404(QRCode, pk=str(qr.serial_id).lower())                                               
---------------------------------------------------------------------------
DoesNotExist                              Traceback (most recent call last)
<snip>
Http404: No QRCode matches the given query.

In [8]:                                                                                    

Can you show me a more concrete example of how you're testing this, much like my paste above?

thomascenni commented 3 years ago

Hello @nshafer Correct, I didn't set any HASHID_FIELD_ALPHABET, I am using the default value:

>>> settings.HASHID_FIELD_ALPHABET
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'

I am trying to reproduce the bug, but it's not happening anymore, I really don't understand what happened when I opened the issue. Thanks for your time.

nshafer commented 3 years ago

No problem, might have just been something else. I'll close the issue for now, reopen if you can duplicate it.