如何在成功的POST请求后更改Class-Based-Views的表单字段填充?

huangapple go评论39阅读模式
英文:

How can I change form field population *after* successful POST request for Class-Based-Views

问题

# forms.py
class CalculatorForm(forms.Form):
    body_weight = forms.FloatField(required=False)

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data['body_weight'] is None:
            cleaned_data['body_weight'] = 50.0
        return cleaned_data
# views.py
class CalculatorView(FormView):
    template_name = 'myapp/mycalculator.html'
    form_class = CalculatorForm

    def get_context_data(self, res=None, **kwargs):
        context = super().get_context_data(**kwargs)
        if res is not None:
            context['result'] = res
        return context

    def form_valid(self, form, *args, **kwargs):
        res = form.cleaned_data['body_weight'] / 2
        return render(
            self.request,
            self.template_name,
            context=self.get_context_data(res=res, **kwargs)
        )
英文:

I want to change the forms initial field population. Here is the catch: I want to change it for the POST request and not for the GET request.

Let's say my app offers a calculation based on a body weight input. If the user inputs a body weight calculation happens with that weight, if not a default of 50 is used. So it is allowed to let the field empty. But after the calculation ran, I want to display that the value used for calculation was 50. That's why I want to populate the field with 50 after the form was initially submitted with an empty value.

# forms.py
class CalculatorForm(forms.Form):
    body_weight = forms.FloatField(required=False)

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data['body_weight'] is None:
            cleaned_data['body_weight'] = 50.0
        # ideally I want to put the logic here
        # self.data[bpka] = 50.0 --> AttributeError: This QueryDict instance is immutable
        # self.fields['body_weight'] = 50.0 --> does not work
        # self.initial.update({'body_weight': 50.0}) --> does not work
        return cleaned_data

I feel like the problem is that I can not reach the bound fields from the clean() method.

If it is not possible within the form the logic has to go to the view I guess. Feel free to modify here:

class CalculatorView(FormView):
    template_name = 'myapp/mycalculator.html'
    form_class = CalculatorForm

    def get_context_data(self, res=None, **kwargs):
        context = super().get_context_data(**kwargs)
        if res is not None:
            context['result'] = res
        return context

    def form_valid(self, form, *args, **kwargs):
        # form['body_weight'] = 50.0 --> does not work
        res = form.cleaned_data['body_weight'] / 2
        return render(
            self.request,
            self.template_name,
            context=self.get_context_data(res=res, **kwargs)
        )

答案1

得分: 1

你可以重写 .form_valid 方法,因为该方法在提交有效的表单数据时被调用。通过这种方式,创建一个带有所需 initial 值的新实例 CalculatorForm,而不是返回默认的 HttpResponseRedirect,而是使用新表单渲染页面。

保留你的表单的 clean 方法不变,然后将修改后的 form.cleaned_data 作为新实例化表单的初始字典传递。

forms.py

class CalculatorForm(forms.Form):
    body_weight = forms.FloatField(required=False)

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data['body_weight'] is None:
            cleaned_data['body_weight'] = 50.0
        return cleaned_data

views.py

class CalculatorView(FormView):
    template_name = "myapp/mycalculator.html"
    form_class = CalculatorForm

    def get_context_data(self, res=None, **kwargs):
        context = super().get_context_data(**kwargs)
        if res is not None:
            context['result'] = res
        return context
    
    def form_valid(self, form):
        body_weight = form.cleaned_data["body_weight"]

        res = body_weight / 2

        form = self.form_class(initial=form.cleaned_data)
        return render(
            self.request, 
            self.template_name, 
            context=self.get_context_data(res=res, form=form, **kwargs)
        )

myapp/mycalculator.html

<body>
    <form action="{% url 'calculator' %}" method="post">
        {% csrf_token %}
        {{ form }}
        <button type="submit">Send</button>
    </form>
    {% if result %}
        <p>{{ result }}</p>
    {% endif %}
</body>
英文:

You can override .form_valid since the method is called when valid form data has been POSTed. In this way creating a new instance of CalculatorForm with the desired initial value and instead of returning a HttpResponseRedirect which is default render the page with the new form.

Keep the clean method of your form as is and then pass the modified form.cleaned_data as the initial dict for your newly instantiated form.

forms.py

class CalculatorForm(forms.Form):
    body_weight = forms.FloatField(required=False)

    def clean(self):
        cleaned_data = super().clean()
        if cleaned_data[&#39;body_weight&#39;] is None:
            cleaned_data[&#39;body_weight&#39;] = 50.0
        return cleaned_data

views.py

class CalculatorView(FormView):
    template_name = &quot;myapp/mycalculator.html&quot;
    form_class = CalculatorForm

    def get_context_data(self, res=None, **kwargs):
        context = super().get_context_data(**kwargs)
        if res is not None:
            context[&#39;result&#39;] = res
        return context
    
    def form_valid(self, form):
        body_weight = form.cleaned_data[&quot;body_weight&quot;]

        res = body_weight / 2

        form = self.form_class(initial=form.cleaned_data)
        return render(
            self.request, 
            self.template_name, 
            context=self.get_context_data(res=res, form=form, **kwargs)
        )

myapp/mycalculator.html

&lt;body&gt;
    &lt;form action=&quot;{% url  &#39;calculator&#39; %}&quot; method=&quot;post&quot;&gt;
        {% csrf_token %}
        {{ form }}
        &lt;button type=&quot;submit&quot;&gt;Send&lt;/button&gt;
    &lt;/form&gt;
    {% if result %}
        &lt;p&gt;{{ result }}&lt;/p&gt;
    {% endif %}
&lt;/body&gt;

huangapple
  • 本文由 发表于 2023年6月29日 22:12:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76581885.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定