So here is my problem: I'm trying to generate a big form of with a bunch of characteristics, some of them to be ticket it off if they are boolean, some to be filled with text and some to be incremented or decremented with a JS spinner. But, and here is the catch, all of them are user generated. What I did was this: In some point I invite the user to create it's characteristics by adding objects to the model Option, in which he tells me the name of the characteristics and it's type (boolean, textual or numerical).
Here is my simplified model:
class Characteristic(models.Model):
option = models.ForeignKey('Option')
class Option(models.Model):
option_name = models.CharField(max_length=100)
OPTION_TYPE_CHOICES = (
('B',u'Bolean'),
('T',u'Textual'),
('N',u'Numerical'),
)
option_type = models.CharField(max_length=1,choices=OPTION_TYPE_CHOICES)
class Boolean(Characteristic):
value = models.BooleanField()
class Textual(Characteristic):
value = models.CharField(max_length=100)
class Numerical(Characteristic):
value = models.PositiveIntegerField()
So far, so good.
The problem starts when generating that form with all the possible characteristics. What I did was this:
Here is my view:
@login_required
def AddCharacteristic(request):
numerical_options = Option.objects.filter(option_type='N')
textual_options = Option.objects.filter(option_type='T')
boolean_options = Option.objects.filter(option_type='B')
NumericalFormset = modelformset_factory(Numerical,extra=len(numerical_options))
TextualFormset = modelformset_factory(Textual,extra=len(textual_options))
BooleanFormset = modelformset_factory(Boolean,extra=len(boolean_options),form=forms.BooleanForm)
if request.method == 'POST':
numerical_formset = NumericalFormset(request.POST,prefix='numerical')·
textual_formset = TextualFormset(request.POST,prefix='textual')
boolean_formset = BooleanFormset(request.POST,prefix='boolean')
if numerical_formset.is_valid() and textual_formset.is_valid() and boolean_formset.is_valid():
numerical_formset.save()
textual_formset.save()
boolean_formset.save()
if 'next' in request.GET:
return HttpResponseRedirect(request.GET['next'])
else:
return HttpResponseRedirect('../../list/')
else:
boolean_formset = BooleanFormset(queryset=Boolean.objects.none(),prefix='boolean',initial=[{'option':n.id} for n in boolean_options])
textual_formset = TextualFormset(queryset=Textual.objects.none(),prefix='textual',initial=[{'option':n.id} for n in textual_options])
numerical_formset = NumericalFormset(queryset=Numerical.objects.none(),prefix='numerical',initial=[{'option':n.id} for n in numerical_options])
return render_to_response('characteristics/add.html', {
'numerical_formset': numerical_formset,
'textual_formset': textual_formset,
'boolean_formset': boolean_formset,
},context_instance=RequestContext(request))
And in my view:
<form method="post">
{% csrf_token %}
{{ numerical_formset.management_form }}
{% for numerical_form in numerical_formset %}
{{ numerical_form }}<br>
{% endfor %}
{{ boolean_formset.management_form }}
{% for boolean_form in boolean_formset %}
{{ boolean_form }}<br>
{% endfor %}
{{ textual_formset.management_form }}
{% for textual_form in textual_formset %}
{{ textual_form }}<br>
{% endfor %}
<button type="submit">Save</button>
<button type="reset">Cancel</button>
</form>
So, it's kind of working, but the main issue so far is:
- I'm not being able to rewrite the widget, transforming the characteristic option field from a dropdown to a label.
- Validation to work. If the user put text in the numerical field or the other way around, Django it's not complaining.
- The general feeling that I mess it up completely and over engineered something. :)