本篇采用分析源码学习的方式。
首先说一下forms模块文件夹结构
forms
|----extras
|----__init__.py
|----widgets.py
|----__init__.py
|----fields.py
|----forms.py
|----formsets.py
|----models.py
|----util.py
|----widgets.py
分析 widgets.py中有Media类
分析其中主要完成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中定义没什么好说的