Django Form Based on Variable Attributes

风格不统一 提交于 2019-12-12 04:31:14

问题


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


回答1:


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.



来源:https://stackoverflow.com/questions/40218992/django-form-based-on-variable-attributes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!