本篇採用分析源碼學習的方式。
首先說一下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中定義沒什麼好說的