1

所以这是我的问题:我正在尝试生成一个具有一堆特征的大表格,其中一些是布尔型的,有些是用文本填充的,有些是递增或递减的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 它不会抱怨。
  • 我总觉得我把事情搞砸了,过度设计了一些东西。:)
4

1 回答 1

1

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

如果还想走自己的路,可以参考EAV动态表格

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

还有其他存储和检索动态数据的方法(如django-hstoredjango-mutant)。我之前已经写过它们。

于 2013-05-06T15:16:30.710 回答