Django - Dynamic form fields based on foreign key
<p>I'm working on creating a database which has programs and these programs have risks. Some background information: Programs (grandparents) have multiple Characteristics (parents) which have multiple Categories (children). I've already constructed a database containing these, however, I want to add risks to a particular program.</p>

<p>That is, for example i have Risk 1 which i want to add to Program 1. I have to answer the following questions: Which characteristics do Risk 1 have? To answer this, I want to construct a dynamic form field. (Note, the amount of characteristics can by any arbitrary number, as well as the amount of categories each characteristic has).</p>

<p>How do I construct such form? I've tried formsets, however I do not know how to implement those in a practical way (I'm still a bit new with Python).</p>

<p>This is a printscreen of how I want it to be implemented: <a href="https://gyazo.com/40c448c0096a9ec5da751ba9883dc912" rel="nofollow">https://gyazo.com/40c448c0096a9ec5da751ba9883dc912</a><br>
However, I have no idea what to do. (Note that the possible answers in the drop down menu are the categories that correspond to that particular Characteristic).
This is what I'm getting: <a href="https://gyazo.com/25fd18e2f31e6931bfd3639ce4be632c" rel="nofollow">https://gyazo.com/25fd18e2f31e6931bfd3639ce4be632c</a></p>

<p>This is the corresponding code I have thus far:</p>

<pre><code># views.py 
def risk_create(request):
program = get_object_or_404(Program, id=20)
RiskFormSet = formset_factory(RiskForm, ...
    ... extra=len(Program.objects.get(id=program.id).char_set.all()))
context = {
    'title': 'New Risk',
    'form': RiskFormSet
}
return render(request, 'risk_form.html', context)


# forms.py
class RiskForm(forms.Form):
for char in Program.objects.get(id=20).char_set.all():
    char = forms.ModelChoiceField(char.cat_set.all(), label=char)
</code></pre>

<p>I'VE FOUND MY ANSWER.</p>

<pre><code>class RiskForm(forms.Form):
def __init__(self, *args, **kwargs):
    programid = kwargs.pop('programid', None)
    super(RiskForm, self).__init__(*args, **kwargs)
    for i in range(0,len(Program.objects.get(id=programid).char_set.all())):
        charid = Program.objects.get(id=programid).char_set.all()[i].id
        charlabel = Program.objects.get(id=programid).char_set.all()[i].label
        self.fields['char_field_%i' %i] = forms.ModelChoiceField(Char.objects.get(id=charid).cat_set.all(), label=charlabel)
</code></pre>

<p>To rephrase your question, are you asking how to pre-populate the form fields? If so consider using <a href="https://docs.djangoproject.com/en/dev/topics/forms/formsets/#using-initial-data-with-a-formset" rel="nofollow">initial values in your formsets</a></p>

python django forms dynamic formset