Помогите понять представление Django - PullRequest
1 голос
/ 11 марта 2011

Я пытаюсь следовать коду, указанному на https://github.com/alex/django-ajax-validation/blob/master/ajax_validation/views.py

Я смог понять маленький кусочек этого. Я добавил комментарии, излагающие мое понимание происходящего.

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

def validate(request, *args, **kwargs):

    # I thing it is some sort of initializations but I cannot really understand what's happening
    form_class = kwargs.pop('form_class')
    defaults = {
        'data': request.POST
    }
    extra_args_func = kwargs.pop('callback', lambda request, *args, **kwargs: {})
    kwargs = extra_args_func(request, *args, **kwargs)
    defaults.update(kwargs)
    form = form_class(**defaults)

    if form.is_valid(): #straightforward, if there is no error then the form is valid
        data = {
            'valid': True,
        }
    else:
    # if we're dealing with a FormSet then walk over .forms to populate errors and formfields
        if isinstance(form, BaseFormSet):  #I cannot really understand what is BaseFromSet
            errors = {}
            formfields = {}
            for f in form.forms: # I am guessing that this is for when there are multiple form submitted for validation
                for field in f.fields.keys(): # I think he is looping over all fields and checking for error. what does add_prefix () return? and what is formfields[]?
                    formfields[f.add_prefix(field)] = f[field]
                for field, error in f.errors.iteritems():
                    errors[f.add_prefix(field)] = error
            if form.non_form_errors():
                errors['__all__'] = form.non_form_errors() # what is the '__all__'?
        else:
            errors = form.errors
            formfields = dict([(fieldname, form[fieldname]) for fieldname in form.fields.keys()])

    # if fields have been specified then restrict the error list
        if request.POST.getlist('fields'): # I am having a hard time understanding what this if statement does.
            fields = request.POST.getlist('fields') + ['__all__']
            errors = dict([(key, val) for key, val in errors.iteritems() if key in fields])

        final_errors = {} # here the author of this code totally lost me.
        for key, val in errors.iteritems():
            if '__all__' in key: 
                final_errors[key] = val
            elif not isinstance(formfields[key].field, forms.FileField):
                html_id = formfields[key].field.widget.attrs.get('id') or formfields[key].auto_id
                html_id = formfields[key].field.widget.id_for_label(html_id)
                final_errors[html_id] = val
        data = {
            'valid': False or not final_errors,
            'errors': final_errors,
        }

    json_serializer = LazyEncoder() # Why does the result have to be returned in json?
    return HttpResponse(json_serializer.encode(data), mimetype='application/json')

validate = require_POST(validate) # a decorator that requires a post to submit

LazyEncoder

class LazyEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Promise):
            return force_unicode(obj)
        return obj

Ответы [ 2 ]

4 голосов
/ 11 марта 2011
form_class = kwargs.pop('form_class')

Это просто извлечение аргумента ключевого слова form_class, переданного через URL-адрес conf.

(r'^SOME/URL/$', 'ajax_validation.views.validate', 
      {'form_class': ContactForm}, # this keyword argument.
       'contact_form_validate') 

BaseFormSet - это просто класс formset, выполняющий работу за сценой. Если вы не знаете, ищите источник! grep -ri "baseformset" . Это бесценный инструмент.

Взгляните на django.forms.formsets, чтобы увидеть, как formset_factory создает новые классы "formset" на основе BaseFormSet, отсюда и заводская часть!


Я предполагаю, что это для случаев, когда для проверки подано несколько форм

Да, именно для этого предназначен набор форм (работа с несколькими формами)


Я думаю, что он просматривает все поля и проверяет наличие ошибок. что возвращает add_prefix ()? а что такое formfields []?

Да, это будет цикл по именам полей.

add_prefix() - для префикса имен полей формы определенной формы. Поскольку набор форм повторяет элементы формы несколько раз, каждому полю требуется уникальный префикс, такой как 0-field1, 1-field1 и т. Д.

formfields - это просто пустой словарь, определенный несколькими строками выше.


что такое ' все '?

__all__ определяется в верхней части django.forms.forms

NON_FIELD_ERRORS = '__all__'

Это просто то, что не связанные с полем ошибки (например, ограничения для двух полей) хранятся в словаре ошибок, а не errors[fieldname].


Мне трудно понять, что делает это утверждение if.

Автор оставил записку:

# if fields have been specified then restrict the error list   
if request.POST.getlist('fields'): 

Он проверяет, указали ли вы какие-либо конкретные поля для проверки в вашем URLConf, это не django, а ajax_validation.

Вы видите, что он перезаписывает свой словарь ошибок, основываясь только на указанных полях, таким образом передавая проверку только для этих полей.

 errors = dict([(key, val) for key, val in errors.iteritems() if key in fields])

здесь автор этого кода полностью потерял меня.

Автор сопоставил пользовательский словарь ошибок и полей с конкретными именами полей с префиксами (в отличие от обычного FormSet с каждой формой, имеющей собственный словарь ошибок, не подозревающий о самом наборе форм), который он предположительно использует в ответе AJAX. проверить все поля.

Как правило, вы можете перебирать набор форм и просматривать ошибки в каждой форме, но это не так, если вам нужно проверить все из них с помощью ajax.

Строка вытягивания html_id в большинстве случаев должна быть прямой, но она есть, потому что виджеты форм МОГУТ добавлять интересные вещи в конец идентификаторов, основываясь на том, является ли виджет, например, радио-выбором.

Из исходных комментариев:

# RadioSelect is represented by multiple <input type="radio"> fields,
# each of which has a distinct ID. The IDs are made distinct by a "_X"
# suffix, where X is the zero-based index of the radio field. Thus,
# the label for a RadioSelect should reference the first one ('_0').

Почему результат должен быть возвращен в json?

Потому что это ajax-запрос, а javascript легко съедает json.


2 - не могли бы вы пройти через эти строки кода ...

extra_args_func = kwargs.pop('callback', lambda request, *args, **kwargs: {})

Либо возвращает аргумент ключевого слова с именем 'callback' (который, если он передается, должен быть функцией, которая принимает request и возвращает словарь), а если нет, возвращает лямбда-функцию, которая возвращает только пустой словарь.

Я не уверен, что конкретно используется для дополнительного контекста. Вы можете использовать его для запуска произвольных фрагментов кода без изменения или подкласса ajax_validation ...

0 голосов
/ 11 марта 2011

Это может помочь вам запустить этот код и поместить точку останова отладчика в какое-либо место, чтобы вы могли пройтись и изучить переменные и методы.Вы можете сделать это, просто поместив эту строку в нужное место:

import pdb; pdb.set_trace()

, и вы будете сброшены в отладчик в консоли.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...