2011-03-11 109 views
1

我试图遵循https://github.com/alex/django-ajax-validation/blob/master/ajax_validation/views.py帮助理解Django视图

我已经能够了解它的一小块列出的代码。我添加了评论,说明我对发生的事情的理解。

我真的很感谢我在旁边的注释中列出的问题上的一些帮助,我不太理解这些问题。

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 
+0

除了这一点,但你看过官方教程? http://docs.djangoproject.com/zh/dev/intro/tutorial01/他们非常好,我建议你如果你还没有做。此外,Django有一些有史以来最好的文档http://docs.djangoproject.com/en/1.2/ – 2011-03-11 01:47:07

+0

我已经通过了教程,我同意它非常有用(并在同一时间我发现它对于初学者来说django可以做的事情是一个非常“沉重的速成课程”)。在这里,我更加困难的理解这些功能在做什么,因为我认为我得到了一般想法。 – 2011-03-11 01:56:23

回答

4
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如何根据BaseFormSet生成新的“formset”类,因此是工厂的一部分!


我猜测,这是因为当有提交验证多个表单

是的,这是一个formset正是为(应对多种形式)


我认为他正在循环所有字段并检查错误。 add_prefix()返回什么?什么是formfields []?

是的,那将通过字段名循环。

add_prefix()用于为表单字段名称添加特定形式的前缀。因为一个formset重复形成元件多次,每个字段需要一个唯一的前缀,比如0-field11-field1

formfields刚好高于几线限定一个空的字典。


什么是 '所有'?

__all__在这儿就是非现场特定错误(如在2个领域的限制)存储下的错误字典,而不是errors[fieldname]django.forms.forms

NON_FIELD_ERRORS = '__all__' 

顶部定义。


我有一个很难理解这个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响应来验证所有字段。

通常情况下,你可以遍历一个formset并办理误差通过基于表格形式,但并非如此,如果你需要通过Ajax来验证他们。

大多数情况下,拉线html_id的线应该是直线前进的,但它的存在是因为表单窗口小部件可以根据窗口小部件是否为无线电选择,将有趣的事情添加到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: {}) 

要么返回名为“回调”(这要是传入,关键字参数应该是接受request并返回一个字典),如果不是这样,返回lambda函数只返回一个空的字典功能。

我不知道具体的用途是什么额外的上下文。您可以使用它来运行任意代码片段,而无需修改或继承ajax_validation ...

+0

感谢您的详细解释:我有两个问题:1.当我在'__all__'问题下说'(例如跨两个字段的约束)',你的意思是检查密码1和密码2是否匹配?你能通过这些代码行''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表单is_valid之前 – 2011-03-11 02:25:31

+0

1:完全是。更确切地说,任何以'clean'方式出现的形式,至于密码,我实际上使用一个字段来清除它们:) 2:它正在寻找一个回调函数,该函数返回带有额外上下文的字典。如果它不存在,它定义一个函数接受通常的参数,返回一个空的字典。 – 2011-03-11 02:51:40

+0

只是想说,谢谢你的时间 – 2011-03-11 03:20:45

0

它可以帮助您运行此代码,并在某处放置调试器断点,以便您可以逐步检查变量和方法。您可以通过简单地将这一行,你要打破这样做:

import pdb; pdb.set_trace() 

,你会被倾入在控制台调试器。

+0

我很好奇我能找到一种方法在我的代码中调试/插入断点。谢谢你提到这个! – 2011-03-11 02:34:07