Это вариант использования для декораторов . Если это что-то более общее, применимо ко всем представлениям (скажем, ведение журнала ошибок), вы можете использовать Django ловушку промежуточного программного обеспечения исключений , но здесь это не так.
Что касается проблемы с повторяющейся строкой ошибок, то Pythoni c способ ее решения состоит в том, чтобы иметь постоянную базовую строку со вставкой {replaceable_parts}
, чтобы в дальнейшем вы могли .format()
их.
Допустим, у нас есть следующий файл decorators.py
:
import functools
from django.shortcuts import render
from requests.exceptions import ConnectionError, RequestException
BASE_ERROR_MESSAGE = 'Could not connect to your box because {error_reason}'
def handle_view_exception(func):
"""Decorator for handling exceptions."""
@functools.wraps(func)
def wrapper(request, *args, **kwargs):
try:
response = func(request, *args, **kwargs)
except RequestException as e:
error_reason = 'of an unknown error.'
if isinstance(e, ConnectionError):
error_reason = 'the host is unknown.'
context = {
'error_message': BASE_ERROR_MESSAGE.format(error_reason=error_reason),
}
response = render(request, 'box/error.html', context)
return response
return wrapper
Мы используем тот факт, что ConnectionError является подклассом RequestException в библиотеке запросов . Мы также могли бы создать словарь с классами исключений в качестве ключей, но проблема здесь в том, что это не будет обрабатывать наследование классов исключений , которое является тем упущением, которое позже выдает тонкие ошибки. Функция isinstance
является более надежным способом выполнения этой проверки.
Если дерево исключений продолжает расти, вы можете продолжать добавлять операторы if
. В случае, если это начинает становиться громоздким, я рекомендую посмотреть здесь , но я бы сказал, что это неприятный запах кода, чтобы иметь так много разветвлений в обработке ошибок.
Тогда в ваших взглядах:
from .decorators import handle_view_exception
@handle_view_exception
def boxinfo(request, url: str):
box = get_box(url)
box.connect()
...
Таким образом, логи обработки ошибок c полностью отделены от ваших представлений, и, что самое главное, их можно использовать повторно.