【问题标题】:Django: Set field choices from view?Django:从视图中设置字段选择?
【发布时间】:2010-08-12 01:16:13
【问题描述】:

我有一些<selects> 需要填充一些choices,这取决于当前登录的用户。我不认为这可能(或容易)从表单类内部完成,所以我可以将选项留空并将它们设置在视图中吗?或者我应该采取什么方法?

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    不确定这是否是最佳答案,但过去我已经在表单的 init 中设置了选择字段的选项 - 您可能会将您的选择传递给您的构造函数形式...

    【讨论】:

    • 或者只是用户对象,其余的我可以在init内部完成。但是如何从 init 内部设置选项?你是像平常一样做self.field = ...,还是可以显式地只修改choices 属性?你手边有一个小代码sn-p吗?
    • 你可以做一些类似 self.fields['field_name'].choices = choice_tuple
    【解决方案2】:

    您可以在视图中动态构建表单(好吧,实际上我宁愿将代码保留在视图之外的它自己的函数中,并在视图中调用它,但这只是细节)

    我在一个项目中就是这样做的:

    user_choices = [(1, 'something'), (2, 'something_else')]
    fields['choice'] = forms.ChoiceField(
        choices=user_choices,
        widget=forms.RadioSelect,
    )
    MyForm = type('SelectableForm', (forms.BaseForm,), { 'base_fields': fields })
    form = MyForm()
    

    显然,您将希望根据当前用户创建user_choices,并添加您需要的任何字段以及选择,但这是基本原则,我将把其余部分留给读者练习。

    【讨论】:

      【解决方案3】:

      考虑到您已将用户作为参数包含在内,我将使用自定义标记来解决此问题。

      在你的 app/templatetags/custom_tags.py 中是这样的:

      @register.simple_tag
      def combo(user, another_param):
          objects = get_objects(user, another_param)
          str = '<select name="example" id="id_example">'
          for object in objects:
              str += '<option value="%s">%s</option>' % (object.id, object.name)
          str += '</select>'
          return mark_safe(str)
      

      然后在你的模板中:

      {% load custom_tags %}
      {% special_select user another_param %}
      

      更多关于自定义标签http://docs.djangoproject.com/en/dev/howto/custom-template-tags/

      【讨论】:

      • ...什么?您是否建议我从 template 中添加额外的字段?这甚至不会验证,因为它们不是有效的choices 的一部分。我认为模板是您最不想这样做的地方......这就是我首先遇到这个障碍的原因。
      • 这可行,但出于几个原因,我个人会避免这样做。它不是 DRY - 这个标签重新定义了现有 Select 小部件已经做的事情,它不可重用 - 这将收集数据的特定过程与该数据的特定呈现相结合,最后它不利用 django 表单,我个人喜欢处理数据输入。但仍然是一个可行的解决方案。
      • @Mark 我忘了说这个解决方案不是基于 django-forms,你应该手动从 POST 中获取值。
      • 恐怕情况更糟。我需要从 clean 方法内部访问此字段,以便我可以对其他字段进行一些条件验证。此外,这使得该解决方案可破解且未经验证......任何人都可以修改 HTML 并插入他们自己的选项,然后我的应用程序就会爆炸,除非它根据 Django 自动为您执行的choices 进行验证。
      【解决方案4】:

      Django 创建动态表单 - 它有效!!

      Forms.py


      class MyForm(forms.Form):
      
               """ Initialize form values from views"""
      
              select=forms.BooleanField(label='',required=False)
      
              field_1=forms.CharField(label='',widget=forms.TextInput(attrs= \
      
                          {'size':'20','readonly':'readonly',}))
      
              field_2=forms.ChoiceField(widget=forms.Select(), \
      
                          choices=((test.id,test.value) for test in test.objects.all()))
      
      
      
              def __init__(self, *args, **kwargs):
      
                 super(MyForm, self).__init__(*args, **kwargs)
      
                 input=kwargs.get('initial',{})
      
                 get_field_1_initial_input_from_views=re.sub("\[|\]|u'|'","",str (input.values()))
      
                 # override field_2 choices based on field_1 input
      
                 try:
      
                     # filter choices
      
                     self.fields[‘field_2'].choices=((test.id,test.value) for test in test.objects.filter ( --------)))
      
                 except:
      
                     pass
      

      Views.py


      def views_function(request,val):
      
              """Dynamically generate input data for formset."""
      
              Initial_data=[]
              initial_data.append({'field_1':data.info})
      
              #Initializing formset
      
              MyFormSet=formset_factory(MyForm,extra=0)
      
              formset=MyFormSet(initial=initial_data)
      
              context={'formset':formset}
      
              if request.method == 'POST':
      
                 formset=MyFormSet(request.POST,request.FILES)
      
                 if formset.is_valid():
      
                     # You can work with the formset dictionary elements in the views function (or) pass it to
                     #Forms.py script through an instance of MyForm
      
                     return HttpResponse(formset.cleaned_data)
      
             return render_to_response(‘test.html', context,context_instance=RequestContext(request))
      

      【讨论】:

      • 你的格式都搞砸了,这对python来说非常关键
      猜你喜欢
      • 1970-01-01
      • 2011-08-20
      • 2019-12-16
      • 2019-09-29
      • 2023-03-12
      • 2017-09-22
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      相关资源
      最近更新 更多