【问题标题】:Using the Django Formset to Generate a Dynamic Form from Multiple Models使用 Django Formset 从多个模型生成动态表单
【发布时间】:2013-04-30 04:13:48
【问题描述】:

所以这是我的问题:我正在尝试生成一个具有一堆特征的大表格,其中一些是布尔型的,有些是用文本填充的,有些是递增的或用 JS 微调器递减。但是,这里要注意的是,它们都是用户生成的。我所做的是:在某些时候,我邀请用户通过向模型选项添加对象来创建它的特征,他在其中告诉我特征的名称和它的类型(布尔值、文本或数字)。

这是我的简化模型:

  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> 

所以,它有点工作,但到目前为止的主要问题是:

  • 我无法重写小部件,将特征选项字段从下拉列表转换为标签。
  • 验证工作。如果用户在数字字段中输入文本或其他方式,Django 它不会抱怨。
  • 总体感觉是我把它完全搞砸了,并且过度设计了一些东西。 :)

【问题讨论】:

    标签: django django-forms django-templates


    【解决方案1】:

    看起来您确实在尝试创建自己的EAV 实现。您可能想改用django-eav

    如果你还想走自己的路,可以参考EAV dynamic form

    此外,还有一篇名为“Dynamic form generation”的好文章,由 Django 的主要开发人员之一 Jacob Kaplan-Moss 撰写(该文章发表于 2010 年,但截至今天,所描述的解决方案仍然有效)。

    还有其他存储和检索动态数据的方法(如django-hstoredjango-mutant)。我已经有written关于他们before

    【讨论】:

    • 附带说明:还有一个名为django-hstore-flattenfields 的应用程序使用hack 使Django generate 动态表单就像ModelForms 一样。
    猜你喜欢
    • 2019-04-15
    • 1970-01-01
    • 2016-10-07
    • 2014-12-07
    • 1970-01-01
    • 2011-06-09
    • 2015-11-23
    • 2019-11-27
    • 1970-01-01
    相关资源
    最近更新 更多