django: поднять BadRequest как исключение?
можно ли поднять BadRequest
как исключение в django?
Я видел, что вы можете поднять 404 [1].
вариант использования: в вспомогательном методе я загружаю json из запроса.ПОЛУЧИТЬ. Если json был вырезан, так как браузер (IE) вырезал url-адрес, я хотел бы вызвать соответствующее исключение.
исключение BadRequest выглядит подходящим, но до сих пор в django нет такого исключения.
в 1.6 есть исключения SuspiciousOperation. Но это не соответствует в моем случае, так как это не связано с безопасностью.
конечно, я мог бы попробовать..за исключением моего вспомогательного метода в методе view, но это не сухо.
у кого-то есть решение, где мне не нужно пытаться..исключение вокруг каждого вызова моего метода helper?
[1] https://docs.djangoproject.com/en/1.6/ref/exceptions/#django.core.urlresolvers.Resolver404
обновление
код пример:
def my_view(request):
data=load_data_from_request(request) # I don't want a try..except here: DRY
process_data(data)
return django.http.HttpResponse('Thank you')
def load_data_from_request(request):
try:
data_raw=json.loads(...)
except ValueError, exc:
raise BadRequest(exc)
...
return data
5 ответов
вам нужно пользовательское промежуточное ПО для обработки исключения, которое вы поднимаете. Вам нужно иметь пользовательские исключения, чтобы проверить его в middleware.
class ErrorHandlingMiddleware(object):
def process_exception(self, request, exception):
if not isinstance(exception, errors.ApiException): # here you check if it yours exception
logger.error('Internal Server Error: %s', request.path,
exc_info=traceback.format_exc(),
extra={
'request': request
}
)
# if it yours exception, return response with error description
try:
return formatters.render_formatted_error(request, exception) # here you return response you need
except Exception, e:
return HttpResponseServerError("Error During Error Processing")
другие ответы объясняют, как вернуть HTTP-ответ со статусом 400.
Если вы хотите подключиться к Django's 400 обработка ошибок, вы можете поднять SuspiciousOperation
исключение или подкласс этого.
посмотреть документы здесь и здесь.
в вашем примере это будет выглядеть так:
from django.core.exceptions import SuspiciousOperation
def load_data_from_request(request):
try:
data_raw = json.loads(...)
except ValueError:
raise SuspiciousOperation('Invalid JSON')
# ...
return data
HttpResponseBadRequest готово к использованию. это реализовано as:
class HttpResponseBadRequest(HttpResponse):
status_code = 400
редактировать из-за обновленного вопроса OP.
Вы можете создать свой собственный помощник и инкапсулировать в него блок try-catch.
def myJsonDec(str):
try:
...
в качестве альтернативы ответу @coldmind (преобразование исключений в промежуточном слое) вы можете поместить декоратор в свою функцию представления, которая делает то же самое. Лично я предпочитаю это, потому что это просто старый Python, и не требует от меня пыли от моих знаний о том, как работает промежуточное ПО Django.
вы не хотите, чтобы stream-of-conciousness встроил все функции в функции просмотра (это делает ваш модуль просмотра зависимым от всех других модулей вашего проекта, ведущих для архитектуры "все зависит от всего остального") вместо этого лучше, если представление просто знает о http. Он извлекает то, что вам нужно из запроса, делегирует некоторую другую функцию "бизнес-логики". Бизнес-логика может делегироваться другим модулям (например, коду базы данных или интерфейсам других внешних систем).) Затем, наконец, возвращаемое значение из вашей бизнес-логики преобразуется в http-ответ функцией view.
но как передать ошибки обратно в представление функция из бизнес-логики (или что она делегирует)? Использование возвращаемых значений раздражает по многим причинам. Например, эти возвращаемые значения ошибок должны быть возвращены в представление из всей вашей кодовой базы. Это часто калечит, потому что вы уже будете использовать возвращаемые значения функций для других целей.
естественный способ справиться с этим-использовать исключения, но представление Django не будет само по себе преобразовывать необработанные исключения в возвращенные коды состояния HTTP (за исключением нескольких особых случаев, как говорит OP.)
Так. Я пишу декоратора, чтобы применить мой взгляд. Декоратор преобразует различные поднятые типы исключений в разные возвращаемые django.http.Значения HttpResponseXXX. е.г:
# This might be raised by your business logic or database code, if they get
# called with parameters that turn out to be invalid. The database code needs
# know nothing about http to do this. It might be best to define these exception
# types in a module of their own to prevent cycles, because many modules
# might need to import them.
class InvalidData(Exception):
pass
# This decorator is defined in the view module, and it knows to convert
# InvalidData exceptions to http status 400. Add whatever other exception types
# and http return values you need. We end with a 'catch-all' conversion of
# Exception into http 500.
def exceptions_to_http_status(view_func):
@wraps(view_func)
def inner(*args, **kwargs):
try:
return view_func(*args, **kwargs)
except InvalidData as e:
return django.http.HttpResponseBadRequest(str(e))
except Exception as e:
return django.http.HttpResponseServerError(str(e))
return inner
# Then finally we define our view, using the decorator.
@exceptions_to_http_status
def myview(self, request):
# The view parses what we need out of incoming requests
data = request.GET['somearg']
# Here in the middle of your view, delegate to your business logic,
# which can just raise exceptions if there is an error.
result = myusecase(data)
# and finally the view constructs responses
return HttpResponse(result.summary)
в зависимости от обстоятельств, вы можете обнаружить, что один и тот же декоратор может работать на многих или всех ваших функциях просмотра.
Я не уверен, что вы имеете в виду, поднимая BadRequest как исключение.
вы можете вернуть ответ с любым кодом состояния, который вам нравится, либо явно используя соответствующий подкласс HttpResponse, либо добавив status
параметр к нормальному ответу.