Django ajax error response best practice

Estoy usando ajax para mejorar la experiencia del usuario en mi proyecto Django. Mi preocupación aquí es cómo responder al error correctamente al navegador. Por lo que sé, puedo:

  1. Valide los datos de solicitud pieza por pieza y guarde la excepción una por una. Si sucede algo malo, levante Http404 u otra excepción para anunciar explícitamente que se ha producido un error. O
  2. simplemente escriba el código sin excepciones y suponga que funcionará. Si sucede algo malo, la excepción no detectada causaría un error interno del servidor, que sigue siendo un error para el navegador

Para mí, el primer método parece más ortodoxo, ya que en Python la filosofía de “Explicit es mejor que Implícito” realmente cuenta. Pero dado que todos los tipos de verificación de excepciones se eliminan de la segunda, es más limpio, menos fragmentado y más legible.

Estoy usando jQuery para manejar la solicitud / respuesta ajax y ambos métodos parecen funcionar. Mis preguntas son:

  1. ¿Ambos métodos son aceptables?
  2. ¿Fallará el segundo método para otras bibliotecas de Javascript?
  3. ¿Cuál es la mejor práctica para esto?

PD. Hago validación de datos esenciales. Por favor, no se desvíe del tema para eso. 🙂

Si devuelve una respuesta con un código de estado de 4xx o 5xx, esto es un error y activará el controlador de error jQueries. Si bien es ciertamente posible devolver el estado 200 cada vez y usar un campo de “error” en la respuesta JSON (como lo sugiere dm03514), esto es malo por dos razones:

  1. Viola las buenas prácticas de HTTP. Hay una razón por la que hay muchos códigos de error definidos

  2. No puede utilizar el hecho de que jQuery ya tiene un controlador de errores que le permite separar el comportamiento normal del manejo de errores.

La mayoría de las veces, la respuesta de error será muy diferente de la respuesta de no error, por lo que simplemente no tiene sentido poner el manejo de estos mensajes en una parte del código JS. Entonces, para resumir, use una respuesta JSON con el estado 200 para sus respuestas normales y devuelva una respuesta (apropiada) a 4xx / 5xx para los errores. Estos también pueden llevar la carga JSON, por lo que su servidor puede agregar detalles adicionales sobre el error.

En mi opinión:

  1. El segundo método no es aceptable.
  2. no fallará ya que el servidor todavía enviará una respuesta http.
  3. Déjame decirte lo que hago en mis proyectos:

cuando se inicia mi proyecto, siempre pre-agrego un módulo llamado errors en la parte superior de la estructura de la carpeta, primero, escribiré una clase de Excepción base que se hereda de la Exception , luego escribiré algunas clases de Excepción comunes como ObjectNotFound , ValidationError desde mi experiencia. Cuando creo que debería generar una excepción en mi código, usaré las excepciones de este módulo, y cuando encuentre un nuevo tipo de excepción que deba manejarse, escribiré una nueva excepción en él.

Entonces es el trabajo de cómo manejarlos. Como está utilizando Django, es muy fácil detectar excepciones a través de un middleware, puede escribir algo como esto:

 from youproject import errors # categorize your exceptions 400_ERRORS = (errors.ValidationError, errors.ParametersMissing, ) 403_ERRORS = (errors.AuthenticationError, ) 404_ERRORS = (errors.ObjectNotFound, errors.ResourceNotExist, ) class ExceptionHandleMiddleware(object): def process_exception(self, request, e): # set status_code by category of the exception you caught if isinstance(e, 400_ERRORS): status_code = 400 elif isinstance(e, 403_ERRORS): status_code = 403 elif isinstance(e, 404_ERRORS): status_code = 404 else: # if the exception not belone to any one you expected, # or you just want the response to be 500 status_code = 500 # you can do something like write an error log or send report mail here logging.error(e) response_dict = { 'status': 'error', # the format of error message determined by you base exception class 'msg': str(e) } if settings.debug: # you can even get the traceback infomation when you are in debug mode response_dict['traceback'] = traceback.format_exc() # set header and return the response .... 

El código anterior es un resumen de cómo gestiono las excepciones en mis proyectos; en general, se trata del control preciso de excepciones, la categorización adecuada de las excepciones y, por supuesto, “Explicit es mejor que la filosofía Implícita”.

=== ACTUALIZACIÓN === Cuando se trata de cómo tratar con las respuestas correspondientes en ajax, puede usar la nueva función en jquery1.5 statusCode :

 $.ajax({ statusCode: { 404: function() { alert('page not found'); } } }); 

De la documentación de jquery:

Un mapa de códigos y funciones HTTP numéricos que se llamarán cuando la respuesta tenga el código correspondiente. Por ejemplo, lo siguiente alertará cuando el estado de respuesta sea un 404

No puedo responder si ambos métodos son aceptables, pero solo puedo decirte lo que hago. En mi opinión, detecto algunos errores específicos / explícitos como:

  • Parámetros inválidos o faltantes en la publicación
  • Errores de alto nivel, como el nombre de usuario ya presente en la base de datos (en una situación de registro, por ejemplo)
  • Todos los demás errores del sistema

Creo que si clasifica sus errores como algunos errores específicos que el usuario debe conocer y luego todo lo demás, entonces su código tendrá como máximo 2 o 3 resultados con rutas de error, lo que en mi humilde opinión no es tan malo. Utilizo JSON para devolver errores y mi estructura suele ser la siguiente:

 respons={} response["error|ok"] response["msg"]="User not found" response["type"]=ERROR_TYPE # only applicable for errors 

Obviamente, esto es bastante básico pero con suerte te da una idea general. Recomendaría no permitir que el usuario vea el error interno del servidor generado por el sistema. Esa es una experiencia de usuario horrible, incluso para aplicaciones internas.

Espero que esto ayude.

No tomaría ninguno de sus enfoques sugeridos. Sugeriría algo como lo que dijo Sid. ¿Por qué no querrías escribir código libre de errores?

Intentaría solucionar todos los errores y errores posibles en el código que escribo en todo momento. Esto incluye la validación de la entrada del usuario. Con ajax, creo que es importante enviar los mensajes al usuario. Esto se logra fácilmente con json.

 response_dict = {} try: # do action that could cause an error except ExpectedError as e: response_dict['success'] = False response_dict['message'] e.msg # or custom message return HttpResponse(json.dumps(repsonse_dict)) 

luego, en su callback ajax, asegúrese de que la respuesta sea válida, si no está alertando al usuario de lo que ha hecho mal. ¡No los dejes colgando, estás haciendo una aplicación para ellos!

Use la opción 1 pero no del modo en que la describe, debe devolver un HttpResponse con status_code 200 indicando en el contenido de la respuesta (usando JSON o algún texto) que se produjo un error de validación, luego, cuando procesa la respuesta en el cliente con JQuery simplemente verifique el contenido de la respuesta y detecte si hubo errores de validación.

Ejemplo de cadena JSON para HttpResponse:

 {"errors": "true", "messages": ["Error #1", "Error #2", "etc."]} 

La opción 2 no es una buena práctica porque los errores internos del servidor ocurren cuando hay una excepción no detectada que fue lanzada por el servidor y que comúnmente es desconocida para el progtwigdor.

No use códigos de estado HTTP para denotar errores de validación, ese no es su propósito.