【问题标题】:Django Form Based on Variable Attributes基于变量属性的 Django 表单
【发布时间】:2017-03-06 06:21:07
【问题描述】:

好吧,我已经为此苦苦挣扎了一段时间,我真的不知道我应该如何在 Python / Django 中做到这一点。也许我的数据库存在根本性的问题。在这种情况下,我们将不胜感激。

这是包含我的数据库结构的打印屏幕:https://gyazo.com/bcb0c1090a005c581f3a62ba24d9302e

注意,一个程序可以有任意数量的字符(Characteristics),每个字符可以有任意数量的猫(Categories)。

现在,在这个特定的测试程序中,我想通过表格添加风险。此风险需要回答所有字符,并为每辆车选择一只猫。 (测试风险 1:{占用:农场,建筑:金属框架,洒水器:是,防护等级:1})

我该怎么做?

这是迄今为止我的风险 Python 代码:

def add_new_risk(request, id=None):
program = get_object_or_404(Program, id=id)
new_risk_form = NewRiskForm(request.POST or None)
if new_risk_form.is_valid():
    new_risk = new_risk_form.save(commit=False)
    new_risk.save()
    return HttpResponseRedirect(program.get_absolute_url() + 'risks/create/' + str(new_risk.id))
context = {
"form": new_risk_form
}
return render(request, 'form.html', context)

因此,首先,我选择要添加风险的程序,然后,我需要回答该程序中包含的所有特征。我试过这个:

def answer_risk_chars(request, id=None, program_id=None):
program = get_object_or_404(Program, id=program_id)
risk = RiskClass(program=Program.objects.get(id=program.id))
chars = program.char_set.all()
for c in chars:
    setattr(risk, c.label, models.CharField(max_length=200, choices=c.cat_set.all(), default=c[0]))

但是,我不知道如何构建一个基于“风险”的表单,它应该包含所有正确的属性。我什至不知道这是否可能。

有什么办法吗?

提前致谢

【问题讨论】:

    标签: python forms dynamic nested parent


    【解决方案1】:

    答案是“是”。您可以在运行时动态构造任何 Django 表单或其他实体,而不是作为声明性类。您可能会发现在How to reduce Django class based view boilerplate 处仔细阅读我的自我回答问题很有用。这与表单无关,但它非常完整地展示了如何从 Django 风格的声明式 class 到同一事物的动态构造。

    如果你用谷歌搜索“Django 动态表单”,你会发现更多与表单相关的东西。您可能会发现您需要的东西已经完成(尝试搜索 Django 软件包网站)。

    如果您需要自己滚动,则需要阅读并重新阅读 Python 的 type 内置函数的三参数形式的(非常简短的)文档,该函数构造类。然后你会尝试类似的东西

    MyDynamicFormClass  = type( 'MyDynamicForm', (forms.Form, ), dict_of_fields)
    

    dict_of_fields 的构造可能类似于(不完整的大纲代码):

    dict_of_fields = {}
    
    for cat in cats:
        choices = [ ]
        for char in get_characteristics( cat):
            choices.append( (db_value_for_char, user_label_for_char) )
    
        dict_of_fields[ cat_name ] = forms.ChoiceField( choices, ...)    
    

    如果所有此类表单都有一组相同的字段,则可以从 MyBaseForm 而不是从 forms.Form 继承以包含它们。还有一些众所周知的方法可以修改 MyBaseForm 的实例以在运行时添加额外的字段,而不是从无到有创建一个全新的类。

    【讨论】:

    • 感谢您的回答。现在将开始深入研究。如果有任何问题,将对此发表评论。仍在努力使用 Python / Django(3 周经验),所以我猜需要一段时间才能完全掌握这一点。
    • 好的。我已经在 Python shell 中工作了我的字段字典(我在我的 Python shell 中得到了我想要的 99% 的东西)。但我的主要问题是 Django 脚本中的实现。我完全不知道要定义什么类,如何定义我的表单等等,它确实有效。
    • 哦,输入已经发表了评论,我无法编辑它。接下来是。我只想放弃它必须添加到的程序。假设我有 URL 127.0.0.1:8000/programs/<PROGRAM_ID>/risks/create。然后它需要自动采用具有程序 的所有特征的形式。如果这有意义
    • 简而言之:网址r'^programs/(?P&lt;progid&gt;)\w+)/risks/create。关联的视图通过模式匹配的程序 ID。使用它从数据库中提取相应的类别和特征。使用它们来动态创建表单类。实例化表单类并以通常的方式将其提供给用户。
    • 好的,我有我的动态表单(据我所知),它正在工作。但是:我已将我的风险等级定义为“BaseClass”,并且我想将“子类”添加到每个单独的程序中。但是,它不会将动态表单字段保存到我的数据库中,而只是将基本属性保存到我的数据库中。知道如何解决这个问题吗?我调查过:stackoverflow.com/questions/32335349/…,但对我必须做的事情一无所知(declared_fieldsets 不再工作)
    猜你喜欢
    • 1970-01-01
    • 2014-05-11
    • 2017-10-12
    • 1970-01-01
    • 2013-03-08
    • 2014-06-06
    • 2011-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多