使用Django Formset从多个模型生成动态窗体 [英] Using the Django Formset to Generate a Dynamic Form from Multiple Models
问题描述
这是我的简化模型:
class Characteristic(models。模型)
option = models.ForeignKey('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)
类布尔值(特征):
value = models.BooleanField()
class Textual(Characteristic):
value = models.CharField(max_length = 100)
class Numerical(Characteristic):
value = models.PositiveIntegerField
到目前为止,很好。
当生成具有所有可能特征的表单时,问题开始。我所做的是这样的:
这是我的观点:
@login_required
def AddCharacteristic(request):
numeric_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(numeric_options))
TextualFormset = modelformset_factory ,extra = len(textual_options))
BooleanFormset = modelformset_factory(Boolean,extra = len(boolean_options),form = forms.BooleanForm)
如果request.method =='POST':
numeric_formset = NumericalFormset(request.POST,prefix ='numeric')·
textual_formset = TextualFormset(request.POST,prefix ='textual)
boolean_formset = BooleanFormset(request.POST,prefix = 'boolean')
如果numeric_formset.is_valid()和t extual_formset.is_valid()和boolean_formset.is_valid():
numeric_formset.save()
textual_formset.save()
boolean_formset.save()
如果next在请求中。 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 boolean_options])
textual_formset = TextualFormset(queryset = textual.objects.none(),prefix ='textual',initial = [{'option':n.id}在textual_options中为n)]
numeric_formset = NumericalFormset(queryset = Numerical.objects.none() prefix ='numeric',initial = [{'option':n.id} for numeric_options])
return render_to_response('features / add.html',{
'numeric_formset':numeric_formse t,
'textual_formset':textual_formset,
'boolean_formset':boolean_formset,
},context_instance = RequestContext(request))
在我看来:
< form method =post >
{%csrf_token%}
{{numeric_formset.management_form}}
{numeric_formset%}中的numeric_form的$%
{{numeric_form}}<峰; br>
{%endfor%}
{{boolean_formset.management_form}}
{boolean_form in boolean_formset%}
{{boolean_form}}< br>
{%endfor%}
{{textual_formset.management_form}}
{text for textual_formset%}
{{textual_form}}< br>
{%endfor%}
< button type =submit> Save< / button>
< button type =reset>取消< / button>
< / form>
所以,这是一种工作,但到目前为止的主要问题是:
- 我无法重写窗口小部件,将特征选项字段从下拉列表转换为标签。
- 验证工作。如果用户将文本放在数字字段中或其他方式,Django就不会抱怨。
- 一般的感觉是我完全弄乱了它,并且设计了一些东西。 :)
真的好像您正在尝试创建自己的 EAV 。您可能希望使用 django-eav 。
如果您仍然想要自己的方式,可以使用 EAV动态表单作为参考。
另外还有一篇很好的文章叫做 还有其他存储和检索动态数据的方法(如 django-hstore 和 django-mutant )。我已经写了关于他们的之前。 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: 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: And in my view: So, it's kind of working, but the main issue so far is:
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()
@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))
<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>
It really looks like you are trying to create your own implementation of EAV. You might want to go with django-eav instead.
If you still want to go your own way, you can use EAV dynamic form as a reference.
Also, there is a nice article called "Dynamic form generation" written by Jacob Kaplan-Moss, one of the lead developers of Django (the article was published in 2010, but, as of today, the described solution is still working).
There are also other approaches for storing and retrieving dynamic data (Like django-hstore and django-mutant). I have already written about them before.
这篇关于使用Django Formset从多个模型生成动态窗体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!