【问题标题】:Rendering different ModelForms based on dropdown field基于下拉字段渲染不同的 ModelForms
【发布时间】:2020-11-07 17:54:18
【问题描述】:

我希望人们能够创建几个不同的配置文件(我们称它们为特殊类型的苹果)。我正在渲染基本 Apple 表单,其中包含 Apple、Red Apple 或 Green Apple 类型的下拉菜单。基于此下拉菜单,我还想显示基于配置文件的 RedAppleProfileForm 或 GreenAppleProfileForm、ModelForms。

如何有条件地呈现这些表单?

  • 我曾尝试使用display: none 渲染它们,并根据所选元素值更改显示,但由于渲染表单的字段是强制性的,即使表单有@987654323,我也无法提交@。如果有办法解决这个问题,这就是一个解决方案。

相关堆栈:How to render django form differently based on what user selects?

关于此堆栈的注意事项:具有 4 个赞成票的解决方案似乎适用于 2 个配置文件,例如红苹果和绿苹果,但在我的场景中,我碰巧有 5 种不同类型的苹果,我不知道我是怎么做到的然后让它工作。接受的解决方案可能会起作用,但我不完全掌握如何?我只是一个 BaseForm 会继承我的所有 5 个 ProfileForms 吗?

Python3.8、Django 3.0

【问题讨论】:

    标签: django django-models django-forms django-templates


    【解决方案1】:

    编辑:我最终彻底检查了我的代码以使用抽象继承,并且效果更好。我建议在尝试使用 Profiles 之前先探索一下。通过抽象继承,您可以更轻松地坚持使用 UpdateView/CreateView 之类的东西

    吓坏了。如果您不需要将下拉列表作为模型的一部分,请使用 crimsonpython24 的答案。如果你这样做了,诀窍就是使用 onchange 下拉列表发回你的视图。

    class AppleForm(forms.ModelForm):
    
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields["color"].widget.attrs.update({"onchange": "this.form.submit()"})
    
        class Meta:
            ...
    

    现在,当用户选择他们想要的 Pawn(或 Apple)类型时,它会发布。

    这是我的观点:

    class AppleCreate(LoginRequiredMixin, View):
        login_url = "/login/"
    
        @staticmethod
        def _create_apple(pawn_form, profile_form):
            apple = apple_form.save()
            profile_obj = profile_form.save(commit=False)
            profile_obj.apple = apple
            profile_obj.save()      
            return redirect(reverse("list_apples"))
    
        def get(self, request):
            context = {"apple_form": AppleForm()}
            return render(request, "my/template.html", context=context)
    
        def post(self, request):
            apple_form = AppleForm(request.POST)
    
            apple_color = request.POST.get("color", "")
            profile_form_selector = {"Red": RedAppleProfileForm(request.POST), "Green": GreenAppleProfileForm(request.POST)}
            profile_form = profile_form_selector.get(apple_color, "")
    
            if apple_color and apple_form.is_valid() and profile_form.is_valid():
                return AppleCreate._create_apple(apple_form, profile_form)
            else:
                return render(request, "my/template.html", context={"apple_form": pawn_form, "profile_form": profile_form})
    

    基本上在你的 post 方法中,如果你有所有的数据,你就可以完成。如果不这样做,则需要重新呈现表单以及要显示的所有字段。

    【讨论】:

      【解决方案2】:

      我认为最好的方法是将您的表单分成两种形式:按钮作为表单本身(以区分要呈现的表单)和“实际”Apple 表单作为您的第二个表单。只要您能找到一种使样式对齐的方法,我认为这样做没有任何问题。实施:

      <!-- you might want to change the styles -->
      <form action="..." method="post">
        <input type="submit" name="red_apple" value="Red Apple" />
        <input type="submit" name="green_apple" value="Green Apple" />
      </form>
      
      <form action="..." method="post">
        <!-- your main form from the view -->
      </form>
      

      views.py

      if 'red_apple' in request.POST:
          # return the right form
      else :
          # return the other form
      

      请注意,您可能希望选择其中一个作为默认设置,否则,只有选择按钮而没有表单会显得很奇怪。

      Reference

      【讨论】:

      • 嗯,我喜欢这可能去的地方。我会试一试,然后回来发表另一条评论!谢谢
      • 好吧.. 10 小时后的工作... 最终只拥有 1 种形式的所有东西,因为我将 Apple 类型作为基本模型的一部分。如果有一种在不知道其类型的情况下访问配置文件的好方法,那么我绝对会走这条路..但我认为我需要有愚蠢的尝试来找出相关名称..我无法完成所有related_name 相同,所以我最终只需要使用 1 个表单就可以了
      猜你喜欢
      • 1970-01-01
      • 2021-12-14
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      相关资源
      最近更新 更多