Выдача 404 вместо 500 при использовании недопустимого uuid

I have a uuid field in my Document model

Если я получаю() свою модель с плохим uuid, я получаю ошибку 500. Эта строка выбрасывает ошибку:

x = Document.objects.get(uuid=object_uuid)

Вместо 500 я хочу 404 ошибку

.

Я написал это, но не хочу вставлять свою функцию везде, где она лишняя (я ленивый)

def is_valid_uuid_or_404(object_uuid):
    try:
        return uuid.UUID(object_uuid)
    except ValueError:
        raise Http404("Invalid uuid")

x = Document.objects.get(uuid=is_valid_uuid_or_404(object_uuid)) #Boring

У кого-то есть хорошая идея, как сделать это лучше?

Вы можете создать пользовательский менеджер моделей и затем добавить к нему пользовательский метод

from django.db import models

class DocumentManager(models.Manager):

    def get_by_uuid(self, uuid, **kwargs):
            
        try:
             return uuid.UUID(object_uuid)
        except ValueError:
            raise Http404("Invalid uuid")
    
        return self.get(uuid=uuid, **kwargs)

class Document(models.Model):
      objects = DocumentManager()


x = Document.objects.get_by_uuid(object_uuid)

Поскольку вы пытаетесь получить этот объект в админке модели, просто используйте метод get_object, который уже есть в админке модели, чтобы получить объект, таким образом вам не нужно будет обрабатывать ошибки, и все, что вам нужно будет обработать, это метод, возвращающий None, поскольку нет подходящего объекта:

from django.contrib.admin.utils import unquote


def change_view(self, request, object_id, form_url="", extra_context=None):
    extra_context = extra_context or {}
    
    to_field = request.POST.get('_to_field', request.GET.get('_to_field'))
    object = self.get_object(request, unquote(object_id), to_field)
    
    extra_context["my_field"] = object.my_field if object else None
    return super().change_view(request, object_id, form_url, extra_context=extra_context)

Общее решение:

Неправильный (недействительный) uuid вызовет эту ошибку, и это даст вам ответ 500, вместо которого вы хотите получить ответ 404. Вместо того чтобы ловить эту ошибку, лучше заранее выполнить оценку. Есть несколько областей, откуда вы могли получить UUID, для простоты предположим, что вы получили его либо из url-параметра, либо из формы. В обоих случаях, конечно, есть соответствующие способы проверки UUID.

Для шаблона url следует использовать uuid конвертер путей, если переданный uuid не является действительным uuid, запрос даже не будет направлен к представлению, и вы получите 404:

path('some-view/<uuid:object_uuid>/', views.some_view),

Далее для формы следует использовать UUIDField [Django-docs] и использовать очистку и валидацию форм:

from django import forms


class SomeForm(forms.Form):
    object_uuid = forms.UUIDField()


# In your view
def some_view(request):
    ...
    form = SomeForm(request.POST)
    if form.is_valid():
        object_uuid = form.cleaned_data['object_uuid']
    ...
Вернуться на верх