Django urls UUID 404 page not found

Posted on February 27, 2021 • eddrichjanzzen

Recently I've been working on a simple api that uses Django Rest Framework. Instead of using integer ids as the primary key identifier, UUIDs are used. The advantage of this approach is to prevent enumeration attacks where the primary key is easily guessable. In addition to this, using UUIDs also guarantees a unique identifier across all systems.

In Django, we are able to define a path to accept a UUID as follows:

urls.py

from django.urls import path, re_path
from tasks.views import api_root_view, task_view, user_view
from django.conf.urls import url

urlpatterns = [
    path('tasks/<uuid:pk>', task_view.TaskDetail.as_view()),
    ...
]

However, I found that the approach above will only work if the UUID supplied matches the specific pattern. This means that supplying an invalid UUID; lets say a UUID that's missing a few characters will always throw a 404 page and will never reach the view.

Original

request:

GET http://localhost:8000/tasks/7cd6fae8-2835-4dac-b44b-53326af162d3

response

{
  "success": true,
  "data": {
    "id": "7cd6fae8-2835-4dac-b44b-53326af162d3",
    "title": "Feed the dogs",
    "description": "Remember to feed the dogs at 8AM",
    "deadline": "2021-02-23T16:37:37Z",
    "created_date": "2021-02-27T05:25:35.579628Z",
    "updated_date": "2021-02-27T05:25:35.579688Z",
    "completed": false
  }
}

Missing few characters

request:


GET http://localhost:8000/tasks/7cd6fae8-4dac-b-53326a3

response:


404 Page not found

Solution

To solve this problem, we can instead make use of re_path, as follows

from django.urls import path, re_path
from tasks.views import api_root_view, task_view, user_view
from django.conf.urls import url

urlpatterns = [
    # accept match any regEx after 'task/'
    re_path(r'^task\/(?P<pk>.+)$', task_view.TaskDetail.as_view()),
]

In this example, we can match any regEx after tasks/ with the pk, so that regardless whether the UUID supplied is invalid, the request would still hit the view, and will respond with details not found, instead of a the 404 page.

Original

request:

GET http://localhost:8000/tasks/7cd6fae8-2835-4dac-b44b-53326af162d3

response:

{
  "success": true,
  "data": {
    "id": "7cd6fae8-2835-4dac-b44b-53326af162d3",
    "title": "Feed the dogs",
    "description": "Remember to feed the dogs at 8AM",
    "deadline": "2021-02-23T16:37:37Z",
    "created_date": "2021-02-27T05:25:35.579628Z",
    "updated_date": "2021-02-27T05:25:35.579688Z",
    "completed": false
  }
}

Missing few characters

request:

GET http://localhost:8000/tasks/7cd6fae8-2835-4dac-b-53326a3

response:

{
  "detail": "Not found."
}

I hope this article will be of help to anyone who encounters a similar issue. 😄 👍

Home

Posts

Projects

Github

Contact

janzzen

Developed by Janzzen Ang powered by Vercel