[Fixed]-Django 2 url path matching negative value

29👍

You can write custom path converter:

class NegativeIntConverter:
    regex = '-?\d+'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%d' % value

In urls.py:

from django.urls import register_converter, path

from . import converters, views

register_converter(converters.NegativeIntConverter, 'negint')

urlpatterns = [
    path('account/<negint:code>/', views.account_code),
    ...
]

4👍

I’m too lazy to make a fancy path converter, so I just captured it as a string and cast it to an integer in the view (with some basic sanity checking to make sure the value can be properly cast to an integer):

urls.py

urlpatterns = [
    path('account/<str:code>/', views.account_code),
    ...
]

views.py (new)

Function-Based View (FBV) example:

from django.http import HttpResponseNotFound

def your_view(request, code):
    try:
        code = int(self.kwargs['code'])  # cast to integer
    except ValueError:
        return HttpResponseNotFound(
            "'code' must be convertible to an integer.")

Class-Based View (CBV) example:

from django.http import HttpResponseNotFound
from django.views.generic import TemplateView

class CodeView(TemplateView):

    def dispatch(self, request, *args, **kwargs):
        try:
            code = int(self.kwargs['code'])  # cast to integer
        except ValueError:
            return HttpResponseNotFound(
                "'code' must be convertible to an integer.")
        return super().dispatch(request, *args, **kwargs)

If you wanted the user to know that a client-side error occurred, you could substitute HttpResponseNotFound with HttpResponseBadRequest, which would give an HTTP status code 400 (Bad Request)


EDIT: The version below produces a server error HTTP response code and is probably not desirable (may show up in error logs, etc.)

views.py (old, left here for historical reasons)

try:
    code = int(self.kwargs['code'])  # cast to integer
except ValueError:
    raise ValueError("'code' must be convertible to an integer.")

Leave a comment