Возвращаемые ошибки формы для запроса AJAX в Django

Я нашел свой путь вокруг Django и jQuery. Я создал базовую форму в Django. При нажатии submit, я использую jQuery, чтобы сделать запрос AJAX к серверу для отправки моих данных. Этот бит работает нормально, и мне удалось сохранить данные. Django возвращает ValidationError, если форма недействительна. Может ли кто-нибудь сказать мне, как вернуть этот набор сообщений об ошибках в ответ на мой запрос AJAX, чтобы я мог легко перебирать его с помощью JS и делать что-нибудь?

Я нашел этот фрагмент. Глядя на бит JS (processJson), вы увидите, что он, кажется, получает сообщения об ошибках, извлекая их из HTML-ответа. Кажется, это довольно глупо для меня. Это лучший способ сделать это?

Извиняюсь за любую неопределенность.

Спасибо заранее.

Ответы

Ответ 1

Ничего себе, это был год с тех пор, как я увидел эту нить. Что ж, с появлением Django 1.3 и магических, недокументированных представлений на основе классов стало проще расширять функциональность Django. Мой проект, в котором широко используются общие представления CRUS на основе класса Django, требует функциональности AJAX и JSON. Я добавил пример того, как я изменил представление обновления Django для поддержки AJAX и вернул ответы AJAX в формате JSON. Посмотрите:

def errors_to_json(errors):
    """
    Convert a Form error list to JSON::
    """
    return dict(
            (k, map(unicode, v))
            for (k,v) in errors.iteritems()
        )

class HybridUpdateView(UpdateView):
    """
    Custom update generic view that speaks JSON
    """
    def form_valid(self, form, *args, **kwargs):
        """
        The Form is valid
        """
        form.save()

        self.message = _("Validation passed. Form Saved.")
        self.data = None
        self.success = True

        payload = {'success': self.success, 'message': self.message, 'data':self.data}

        if self.request.is_ajax():
            return HttpResponse(json.dumps(payload),
                content_type='application/json',
            )
        else:
            return super(HybridUpdateView, self).form_valid(
                form, *args, **kwargs
            )

    def form_invalid(self, form, *args, **kwargs):
        """
        The Form is invalid
        """
        #form.save()

        self.message = _("Validation failed.")
        self.data = errors_to_json(form.errors)
        self.success = False

        payload = {'success': self.success, 'message': self.message, 'data':self.data}

        if self.request.is_ajax():
            return HttpResponse(json.dumps(payload),
                content_type='application/json',
            )
        else:
            return super(HybridUpdateView, self).form_invalid(
                form, *args, **kwargs
            )

Ответ JSON содержит три поля - message (который является читаемым человеком), data (в данном случае это будет список ошибок формы) и success (который является либо true, либо false, указывая, был ли запрос успешным или нет.). Это очень легко обрабатывать на стороне клиента jQuery. Образец ответа выглядит так:

Content-Type: application/json

{"message": "Validation failed.", "data": {"host": ["This field is required."]}, "success": false}

Это всего лишь пример того, как я сериализовал ошибки формы в JSON и реализовал ее в универсальном представлении на основе классов, но может быть использован для работы с обычными представлениями стиля.

Ответ 2

Этот вопрос старый, но я думаю, что самый короткий ответ мог бы использовать простой json в таком виде.

from django.utils import simplejson

def ajax(request):
    if request.method == 'POST':
        form = someForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponse(something)
        else:
            errors = form.errors
            return HttpResponse(simplejson.dumps(errors))
    else:
        return HttpResponse(something)

теперь вы можете получить доступ к данным в вашем jquery, таком как Calvin, описанном выше. JQuery упрощает обработку данных, вы можете сделать что-то вроде этого:

var errors = jQuery.parseJSON(data)
    alert(errors.username)

Ответ 3

Когда я использую проверку на лицевой стороне, обычно ответ содержит куски, к которым вы можете получить доступ через точечную нотацию (dataReturned.specificData).

Основываясь на том, что и как вы возвращаете данные, является ключом к доступу к нему. Чем модульнее вы обрабатываете возвращаемые данные, тем легче получить доступ.

// Start ajax request to server
$.ajax({
    url: '/path_to_service',
    type: 'POST',
    data: { key: value },

    // Do something with the data
    success: function(data) {
        // Data is everything that is returned from the post
        alert(data);
        // data.message could be a piece of the entire return
        alert(data.message);
    } error: function(data) { // Handle fatal errors }
});

Ответ 4

Вы можете использовать мою библиотеку adjax, чтобы справиться с этим для вас. Установите приложение где-нибудь на своем пути, свяжите файл adjax.js и добавьте в свой вид следующее:

import adjax
@adjax.adjax_response
def my_view(request):
    # prepare my_form with posted data as normal
    adjax.form(request, my_form)

Включить форму с помощью javascript после загрузки файла adjax.js:

 $('form').adjaxify();

И наслаждайтесь: -)

Дополнительные функции здесь: http://adjax.hardysoftware.com.au/how/. Я выпущу версию "1.0" на следующей неделе, дайте мне знать, как все идет. Проект кода Google находится здесь: http://code.google.com/p/django-adjax/

Ответ 5

Я знаю, что это старый и ответивший вопрос! Еще хотел бы внести свой вклад. Решение, которое мне больше всего нравится, - это использовать декоратор для методов, которые должны быть ошибочными json.

import traceback,sys,simplejson

def unhandled(e):
  """
     Helper function to format an exception and it stack
  """
  exc_type, exc_value, exc_traceback = sys.exc_info()
  lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
  stack =  ''.join(line for line in lines)
  return HttpResponse(simplejson.dumps({"error":-1, "response": e.message ,"stack":stack}), content_type='application/json')


def use_json_except(f):
  def new_f(*args):
    try:
      return f(*args)
    except Exception as e:
      return unhandled(e)
    return new_f

Затем вы определяете свой метод Django:

 @use_json_except
 def add_annotation(request):
     ....

Декоратор поймает любые неперехваченные исключения и выведет json с информацией об ошибке и стек.

Я лично считаю это очень хорошим решением для сервера django, который смешивает ответы html и json.