Django中的动态表单要求

时间:2010-02-09 13:41:42

标签: python django forms

我即将开始一个大型的Django项目。关键功能是表单处理。应用程序的用户将会使用很多表单。一个要求是应该可以在应用程序的管理界面中编辑表单。

也就是说,不需要添加/删除表单字段。但是应该可以编辑表单字段属性。例如,改变哪些领域是必需的等等。

任何人都有如何做到这一点的好解决方案。我想我可能必须继承我想要动态的字段并在那里做一些事情。我猜所有模型字段都必须有“blank = True / null = True”,并且有些如何在单独的模型(?)中添加一些元信息,这些模型声明了需要字段的模型。然后在显示和验证表单时使用该信息。

在我开始这样做之前,我真的想要一些关于如何设计这样一个解决方案的意见,任何人都有关于应该如何做的想法?


经过更多的研究,我已经了解到你可以使用工厂函数来执行一个工具函数,它将返回具有给定属性集的表单。所以看起来问题并不难解决。

我会创建一个函数,返回一个设置了正确属性/字段的表单。但是我没有找到一个好的解决方案的部分是如何在管理界面中管理它。我想我会创建一个db.Model来存储有关其他模型字段的信息。在哪里我可以设置哪些是必需的等等。

然后在返回表单的函数中,转到该模型并返回具有正确属性的表单。但是如何以一种好的方式制作该模型(应该反映另一个模型领域)?

2 个答案:

答案 0 :(得分:2)

您应该使用某些模型。对于可能以这种方式自定义的每个表单,必须创建新的数据库条目。我猜,它应该是这样的:

class FormSettings(Model):
  form = CharField(..)

class FormAttrib(Model):
  form_settings = ForeignKey(FormSettings)
  field = CharField(..)
  attrib_name=CharField(..)
  attrib_value=CharField(..)

在FormSettings.form中,您应该存储一些表单的地址,比如说。当构建表单时(在 init 中),它应该在db中查找条目并使用为其描述的attribs。

如果您为表单使用自己的元类并在创建类时在数据库中注册(创建正确的FormSettings条目),则可以轻松创建数据库条目。它将在流程开始时完成一次,这不应该那么糟糕。

我希望它有所帮助。如果您有其他问题,我会很乐意提供帮助:-)我喜欢django的非标准设备:-)这是所有乐趣开始的地方: - )

修改

好吧,让我们说,你想拥有app food并在food_name字段中形成FavouriteFoodForm。您将formsettings表中的数据库存储为food.FavouriteFoodForm并添加一个属性设置:field ='food_name',attrib_name ='required',attribute_value ='True'(它不完美,但仍然不是那么糟糕')。< / p>

在FavouriteFoddForm中没有你在数据库中查找设置,所以你这样做:

settings = FormSettings.objects.get(form=app_name + self.__class__.name)

并迭代设置

for setting in settings.formattrib_set():

在这里你简单地调用exec并设置适当的属性:

exec("getattr(self, settings.field)[attrib_name] = %s" % attrib_value)

这应该将属性设置为required = True。

答案 1 :(得分:2)

这不是你问题的确切答案,但我做了类似我认为可能对你有用的东西。我创建了一个完全可自定义的表单,以便最终用户可以自定义表单。

我最终得到了2个模型,BuiltFormBuiltFormField

class BuiltForm(models.Model): 
    name = models.CharField(max_length=32) 
    def form(self, data=None, initial=None):
        form = BuiltFormGenericForm(data, initial=initial)
        form.addBuiltFormFields(BuiltFormField.objects.filter(builtform=self, disabled=0))
        return form            

class BuiltFormField(models.Model):
    builtform = models.ForeignKey(BuiltForm)
    type = models.CharField(max_length=32, choices=ALL_FIELD_TYPES)
    label = models.CharField(max_length=32)
    fieldname = models.CharField(max_length=32)
    helptext = models.CharField(max_length=256, blank=True)
    required = models.BooleanField(default=False)
    sort_order = models.IntegerField(default=0)
    disabled = models.BooleanField(default=False)
    options = models.TextField(blank=True)
    def field(self):
        field = ALL_FIELD_MAPS.get(self.type)
        ## Build out the field, supplying choices, `required`, etc.

有一些事情是不正常的。 ALL_FIELD_TYPES是表单中允许的字段类型的映射。这与dict()结合使用,以识别应该为此字段使用的类(CharFieldEmailFieldChoiceField等)。 options也是pickle d个选项列表,供以后在ChoiceField中使用。这使我可以创建一个任意的选项列表,而无需单独调用数据库。

另一个主要部分是自定义Form类,它允许自己使用BuiltForm中的字段填充。我看起来像这样:

class BuiltFormGenericForm(forms.Form):
    built_form_fields = {}
    builtform = None
    def addBuiltFormFields(self, fields):
        for field in fields:
            self.fields[field.label] = field.field()
            self.built_form_fields[field.pk] = field
    def is_valid(self):
        # Do validation here.  My code for this is pretty big because of custom fields
        # and calculations that I have to squeeze in.

BuiltFormField对象不是通过管理界面创建的,而是通过一个包含大量JavaScript的自定义对象来创建,以使其对用户友好,但您当然可以公开部分BuiltFormField对象。 1}}管理界面中的模型,以便更新它们。

希望这有助于您为表单制作模型。