本篇采用分析源码学习的方式。
首先说一下forms模块文件夹结构
forms |----extras |----__init__.py |----widgets.py |----__init__.py |----fields.py |----forms.py |----formsets.py |----models.py |----util.py |----widgets.py
分析其中主要完成2件事情
1:js和css路径设置
2:js和css路径渲染
渲染部分 def render(self): return mark_safe('\n'.join(chain(*[getattr(self, 'render_' + name)() for name in MEDIA_TYPES]))) def render_js(self): return [format_html('<script type="text/javascript" src="{0}"></script>', self.absolute_path(path)) for path in self._js] def render_css(self): # To keep rendering order consistent, we can't just iterate over items(). # We need to sort the keys, and iterate over the sorted list. media = sorted(self._css.keys()) return chain(*[ [format_html('<link href="{0}" type="text/css" media="{1}" rel="stylesheet" />', self.absolute_path(path), medium) for path in self._css[medium]] for medium in media])
接下来定义部件类
部件基类(包含,渲染,label提示,取值),封装常见的form控件类。主要是显示部分。
接下来看fields.py
fields类封装了对应的部件与程序员交互部分的方法。(验证,更多显示操控。初始化,本地化等操作)
并基于部件,做了1些深层的字段封装(邮件字段,邮箱字段,时间,日期,正则。)。
主要目的用于将orm的字段对应到前端。对应到部件。
接下来看forms.py
有了部件和field的封装以后。
1个form中有多个fields如何处理。显示。
接下来看formsets.py文件,进入更牛B的批量生产工厂
def formset_factory(form, formset=BaseFormSet, extra=1, can_order=False, can_delete=False, max_num=None): if max_num is None: max_num = DEFAULT_MAX_NUM absolute_max = max(DEFAULT_MAX_NUM, max_num) attrs = {'form': form, 'extra': extra, 'can_order': can_order, 'can_delete': can_delete, 'max_num': max_num, 'absolute_max': absolute_max} return type(form.__name__ + str('FormSet'), (formset,), attrs)
新建1个formFormSet的类。基类是BaseFromSet。属性有 form,extra。。。
在初始化内部调用
def _construct_forms(self): self.forms = [] for i in xrange(min(self.total_form_count(), self.absolute_max)): self.forms.append(self._construct_form(i))
根据数量构造form
下面是抽象出来的模拟理解过程的代码
def with_metaclass(meta, base=object): return meta("NewBase", (base,), {}) def get_declared_fields(base, attrs): print base, attrs class DeclarativeFieldsMetaclass(type): def __new__(cls, name, bases, attrs): attrs['base_fields'] = get_declared_fields(bases, attrs) new_class = super(DeclarativeFieldsMetaclass, cls).__new__(cls, name, bases, attrs) return new_class class BaseForm(object): def __init__(self): pass class Form(with_metaclass(DeclarativeFieldsMetaclass, BaseForm)): pass class BaseFormSet(object): def __init__(self): pass def formset_factory(form, formset=BaseFormSet, extra = 1): attrs = {'form':form, 'extra':extra} return type(form.__name__ + str("FormSet"), (formset,), attrs) class subForm(Form): def __init__(self): print 'subForm' formsets = formset_factory(subForm) print formsets print formsets.__dict__
接下来看models.py文件
Helper functions for creating Form classes from Django models and database field objects.
models.py中封装了类似formset的方法。与其他方法(下次看文档时候在具体分析)
关于其中的用法
http://my.oschina.net/xorochi/blog/125802
http://i.appspot.com/blog/2009/jan/11/django-dynamic-modelform/
官方使用方法
https://docs.djangoproject.com/en/dev/topics/forms/modelforms/#modelforms-factory
util.py中定义没什么好说的