147 dynamodel=dynamodel, |
147 dynamodel=dynamodel, |
148 dynabase=dynaform, |
148 dynabase=dynaform, |
149 dynainclude=dynainclude, |
149 dynainclude=dynainclude, |
150 dynaexclude=dynaexclude, |
150 dynaexclude=dynaexclude, |
151 dynaproperties=dynaproperties) |
151 dynaproperties=dynaproperties) |
|
152 |
|
153 |
|
154 class DynaFieldMetaclass(type): |
|
155 """The DynaField Meta class, adding support for dynamic properties. |
|
156 |
|
157 The new DynaField class that is created by class function is only |
|
158 modified slightly. The only difference is that if the field class has |
|
159 a dynaproperties property, it will be used to define additional properties |
|
160 for the field. |
|
161 |
|
162 The 'dynaproperties' property (if present), is expected to be iterable as a |
|
163 dictionary (with iteritems). The keys are used as the property names, |
|
164 and the values are used as the property value. |
|
165 """ |
|
166 |
|
167 def __new__(cls, name, bases, attrs): |
|
168 """See djangoforms.ModelFormMetaclass on how the __new__ method |
|
169 is used, for an explanation on how this class modifies the default |
|
170 behavior, see the DynaFormMetaclass's docstring. |
|
171 """ |
|
172 |
|
173 # Retrieve the Meta class, if present |
|
174 dynaproperties = attrs.get('dynaproperties', {}) |
|
175 |
|
176 for key, value in dynaproperties.iteritems(): |
|
177 attrs[key] = value |
|
178 |
|
179 # Leave the rest to type |
|
180 return super(DynaFieldMetaclass, cls).__new__(cls, name, bases, attrs) |
|
181 |
|
182 |
|
183 def newDynaField(field, base, passthrough): |
|
184 """Creates a new form DynaField class. |
|
185 |
|
186 The returned class extends base, but with the following additions: |
|
187 * It has a dynaproperties attribute as extracted from field. |
|
188 * It's __metaclass__ is set to DynaFieldMetaclass (which inherits from |
|
189 the default type class). |
|
190 |
|
191 See DynaFieldMetaclass for an explanation on how the dynaproperties |
|
192 property is used to construct the DynaForm class. |
|
193 """ |
|
194 |
|
195 # pass only known accepted arguments to super |
|
196 init_args = dicts.filter(field, passthrough) |
|
197 |
|
198 properties = field.copy() |
|
199 |
|
200 # all pass through arguments are handled by super |
|
201 for key in passthrough: |
|
202 if key in properties: |
|
203 del properties[key] |
|
204 |
|
205 class DynaField(base): |
|
206 """The dynamically created Field class. |
|
207 """ |
|
208 |
|
209 __metaclass__ = DynaFieldMetaclass |
|
210 dynaproperties = properties |
|
211 |
|
212 def __init__(self): |
|
213 """Pass through the init args to super. |
|
214 """ |
|
215 |
|
216 super(DynaField, self).__init__(**init_args) |
|
217 |
|
218 return DynaField |