基于变量属性的Django表单 [英] Django Form Based on Variable Attributes

查看:186
本文介绍了基于变量属性的Django表单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我一直在努力一段时间,我无法真正弄清楚我应该如何在Python / Django这样做。也许我的数据库有根本的错误。在这种情况下,请谅解。



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



注意,一个程序可以有任意数量的Chars(特征),每个可以有任意数量的猫(类别)。



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



我该怎么做?

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

  def add_new_risk(request, id = None)
program = get_object_or_404(Program,id = id)
new_risk_form = NewRiskForm(request.POST或None)
如果new_risk_form.is_valid():
new_risk = new_risk_form.save(commit = False)
new_risk.save()
返回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 :
setattr(risk,c.label,models.CharField(max_length = 200,choices = c.cat_set.all(),default = c [0]))
但是,我不知道如何构建一个基于风险的表单,它应该包含所有正确的属性。我不知道这是否可以。



有没有办法这样做?



感谢提前

解决方案

答案是是。您可以在运行时动态构建任何Django表单或其他实体,而不是声明类。您可能会发现在这里仔细阅读我自我回答的任务是有用的如何减少基于Django类的视图样板。这不是关于表单,而是一个非常充分的阐述,如何从一个Django风格的声明式到同一件事情的动态构造。



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



如果您需要自己滚动,则需要阅读并重新阅读Python的 type builtin,它构造类。然后你会尝试像

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

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

  dict_of_fields = {} 

猫中的猫:
选项= []
在get_characteristics(cat)中的char:
choices.append((db_value_for_char,user_label_for_char))

dict_of_fields [cat_name] = forms.ChoiceField(选择, 。)

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


Allright, I've been struggling with this for a while now and I can't really figure out how I should be doing this in Python / Django. Maybe there is something fundamentally wrong with my database. In that case, help is appreciated.

This is a print screen that contains my database structure: https://gyazo.com/bcb0c1090a005c581f3a62ba24d9302e

Note, a program can have an arbitrary amount of Chars (Characteristics), which each can have an arbitrary amount of cats (Categories).

Now, in this particular test program, i want to add a Risk by means of a form. This Risk needs to answer all the Chars, and choose one of the Cats for each Car. (Test Risk 1: {Occupancy: Farm, Construction: Metal Frame, Sprinklers: Yes, Protection Class: 1})

How do I do this?

This is my Python code for Risks thus far:

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)

Thus first, I choose which program I want to add the risk to, then, I need to answer all the characteristics that are contained within that program. I tried this:

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]))

However, I do not know how to construct a form based on 'risk', which should contain all the correct attributes. I do not even know whether this is possible.

Is there any way to do this?

Thanks in advance

解决方案

The answer is "yes". You can construct any Django form or other entity dynamically at runtime rather than as a declarative class. You may find it useful to peruse my self-answered questiion here How to reduce Django class based view boilerplate. It's not about forms, but it is a pretty full exposition of how you get from a Django-style declarative class to a dynamic construction of the same thing.

If you google "Django dynamic form" you will find a lot more form-related stuff. You may find that what you need has already been done (try searching the Django packages web site).

If you need to roll it yourself, you need to read and re-read the (quite brief) documentation of the three-argument form of Python's type builtin, which constructs classes. Then you'll try something like

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

where dict_of_fields might be constructed something like (incomplete, outline code):

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, ...)    

If there are a set of fields that are the same for all such forms, you could inherit from MyBaseForm rather than from forms.Form to include them. There are also well-known ways of modifying an instance of MyBaseForm to add extra fields at runtime, rather than creating a completely new class from nothing.

这篇关于基于变量属性的Django表单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆