我想这是一个多Django的一个蟒蛇问题的,但我不能复制这种行为在其他地方,所以我将使用精确的代码预期不起作用。
我是工作在Django中一些动态的形式,当我发现这个工厂函数摘录:
def get_employee_form(employee):
"""Return the form for a specific Board."""
employee_fields = EmployeeFieldModel.objects.filter(employee = employee).order_by ('order')
class EmployeeForm(forms.Form):
def __init__(self, *args, **kwargs):
forms.Form.__init__(self, *args, **kwargs)
self.employee = employee
def save(self):
"Do the save"
for field in employee_fields:
setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
return type('EmployeeForm', (forms.Form, ), dict(EmployeeForm.__dict__))
[从: http://uswaretech.com/blog/2008/10/dynamic-forms-with-django/ ]
还有一件事我不明白, 为什么归国修改EmployeeForm不会做的伎俩? 我的意思是这样的:
def get_employee_form(employee):
#[...]same function body as before
for field in employee_fields:
setattr(EmployeeForm, field.name, copy(type_mapping[field.type]))
return EmployeeForm
当我试图修改返回Django的类忽略我的其他字段,但的返回类型()结果完美。
梅里的假设是正确的:一元类确实是罪魁祸首。 无需猜测,只看来源 :元类是DeclarativeFieldsMetaclass
目前在该文件的53线,并增加了属性base_fields
,可能media
依据是什么属性的类具有在创建时。 在管线329 FF你看:
class Form(BaseForm):
"A collection of Fields, plus their associated data."
# This is a separate class from BaseForm in order to abstract the way
# self.fields is specified. This class (Form) is the one that does the
# fancy metaclass stuff purely for the semantic sugar -- it allows one
# to define a form using declarative syntax.
# BaseForm itself has no way of designating self.fields.
__metaclass__ = DeclarativeFieldsMetaclass
这意味着有产生与基地一类新的一些脆弱type
-提供的黑魔法可能会或可能不会进行过! 更坚实的方法是使用的类型EmployeeForm
这将拾取可能涉及任何元类-即:
return type(EmployeeForm)('EmployeeForm', (forms.Form, ), EmployeeForm.__dict__)
(无需复制__dict__
,顺便说一句)。 所不同的是微妙但重要的:而不是使用直接type
的3-ARGS形式,我们使用1-arg格式拿起类型(即,元类)的形式的类,然后调用该元类在3- ARGS形成。
恶毒地magicallish确实,但随后这是其“纯粹是为了语义糖花式元类的东西”&C做这样使用框架的缺点:你在三叶草是只要你想要做什么的框架支持,而是要离开的那支哪怕是一点点,可能需要反补贴巫术(这大大有助于解释为什么经常我宁愿使用一个轻量级的,透明的设置,如WERKZEUG,而不是不吝魔术对我来说简直导轨或Django的做了一个框架某种方式:我的黑色魔法的掌握并不意味着我很高兴有使用它在普通的生产代码...但是,这是另一个讨论;-)。
我只是试图与直非Django的类和它的工作。 因此,这不是一个Python的问题,而是一个Django的问题。
在这种情况下(虽然我不是100%确定),它是类的创建过程中Form类做什么的问题。 我认为它有一个元类,而这个类元将完成类的创建过程中的形式初始化。 这意味着,类创建后添加的任何字段将被忽略。
因此,你需要创建一个新的类,如与类型()语句来完成的,这样的元类的类创建代码参与,现在有了新的领域。
值得一提的是此代码段是一个非常贫穷的手段所期望的结束,涉及约Django表单对象普遍存在一个误区 - 一个Form对象应该映射一个对一个与HTML表单。 做这样的事情(不需要使用任何魔法元类搞乱)正确的方法是使用多个表单对象和内联表单集 。
或者,如果一些奇怪的原因,你真的想保持对事物的单一形式的对象,只是操作在窗体的__init__方法self.fields。