Django:获取下拉值并为基于类的视图选择动态表单字段

时间:2019-06-28 01:00:19

标签: python django django-forms

在我当前的代码中(见下文),我从下拉选择字段中检索选定的值,例如值“ 1”。

recipe_choice = request.GET.get('recipe_select', False)

我在IF逻辑中使用此值来选择不同的形式,例如

if recipe_choice == '1':
        ingredients_form = HamburgerForm(request.POST)

然后,我返回一个由下拉选择字段和所选表单组成的上下文。

当我将其作为函数调用时,一切正常,可以使用“请求”将下拉选项提取为GET。

例如作为功​​能:

path('cooking/', cooking, name="cooking")

但是,我想问一下,当改用基于类的FormView时如何获得相同的结果,例如:

path('cooking/', CookingView.as_view(), name="cooking")

我遇到的问题是,我无法从下拉列表中检索选定的值,也无法在get_context_data中找到要在IF语句中使用的值,因此无法将旧函数转换为新的CookingView(FormView):

class CookingView(FormView):
    form_class = CookingForm
    template_name = 'form/cooking.html'

    def get_context_data(self, **kwargs):

        """
       # some logic to get a desired form, such as

        ingredients_form = []
        if recipe_choice == '1':
            ingredients_form = HamburgerForm(request.POST)
        elif recipe_choice == '2':
            ingredients_form = PancakeForm(request.POST)

        """

        context = super(CookingView, self).get_context_data(**kwargs)
        context['ingridients_form'] = ingredients_form
        return context

问:如何将这种逻辑放入基于类的FormView中?

下面,我提供了当前有效的代码(作为函数)。

views.py

def cooking(request):
    context = {}
    recipe_choice = request.GET.get('recipe_select', False)

    ingredients_form = []
    if recipe_choice == '1':
        ingredients_form = HamburgerForm(request.POST)
    elif recipe_choice == '2':
        ingredients_form = PancakeForm(request.POST)

    context['cookbook_form'] = CookingForm(request.GET or None)
    context['ingridients_form'] = ingredients_form

    return render(request, 'form/cooking.html', context)

models.py

class Ingridients(models.Model):
    # for hamburgers
    cheese  = models.IntegerField(default=0)
    ham     = models.IntegerField(default=0)
    onion   = models.IntegerField(default=0)
    bread   = models.IntegerField(default=0)
    ketchup = models.IntegerField(default=0)
    # for pancakes
    milk    = models.IntegerField(default=0)
    butter  = models.IntegerField(default=0)
    honey   = models.IntegerField(default=0)
    eggs    = models.IntegerField(default=0)

forms.py

class CookingForm(Form):
    RECIPES = (
        (1, 'Hamburger'),
        (2, 'Pancakes')
    )
    recipe_select = ChoiceField(choices=RECIPES)


class HamburgerForm(forms.ModelForm):
    class Meta:
        model = Ingridients
        fields = ['cheese', 'ham', 'onion', 'bread', 'ketchup']

class PancakeForm(forms.ModelForm):
    class Meta:
        model = Ingridients
        fields = ['milk', 'butter', 'honey', 'eggs']

cooking.html

{% load crispy_forms_tags %}
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>

  <body>
  <form id="cookselect_form" method="GET">
    {{ cookbook_form|crispy }}
    <div class="btn-group btn-group-justified" role="group">
      <div class="btn-group" role="group">
        <button class="btn btn-primary" type="submit">Choose Recipe</button>
      </div>
    </div>
  </form>

  <form id="ingridientslist_form" method="POST">
    {% csrf_token %}
    {% crispy ingridients_form %}
  </form>
  </body>
</html>

1 个答案:

答案 0 :(得分:1)

我认为您可以这样处理:

我要重写get_form_class方法,以确定在HamburgerForm和PancakeForm之间呈现哪种形式。然后,我将CookingForm作为上下文传递给get_context_data方法。

class CookingView(FormView):
    template_name = 'form/cooking.html'
     success_url = '/some_url/'

    def get_form_class(self):
       recipe_choice = self.request.GET.get('recipe_select', '1')
       if recipe_choice == '1':
        return HamburgerForm
       elif recipe_choice == '2':
        return PancakeForm

    def get_context_data(self, **kwargs):
        context = super(CookingView, self).get_context_data(**kwargs)
        context['cookbook_form'] = CookingForm()
        return context

我也正在更新模板(使用form而不是ingridients_form)。

{% load crispy_forms_tags %}
<!DOCTYPE html>

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Title</title>
  </head>

  <body>
  <form id="cookselect_form" method="GET">
    {{ cookbook_form|crispy }}
    <div class="btn-group btn-group-justified" role="group">
      <div class="btn-group" role="group">
        <button class="btn btn-primary" type="submit">Choose Recipe</button>
      </div>
    </div>
  </form>

  <form id="ingridientslist_form" method="POST">
    {% csrf_token %}
    {% crispy form %}
  </form>
  </body>
</html>