You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django+HTMX响应返回旧表单数据问题求助

问题场景与代码实现

我修改了Django的UpdateView,让它在pk=0时支持创建请求:

class ObjectView(UpdateView):

    def get_object(self, queryset=None):
        if self.kwargs.get(self.pk_url_kwarg) == 0:
            return None
        return super().get_object(queryset)

    def form_valid(self, form):
        if self.request.htmx:
            return self.render_to_response(self.get_context_data(form=form))
        return redirect(self.object.get_absolute_url())

在PartView子类中,我新增逻辑:当price字段更新时,同步将price_date设为当前日期:

class PartView(ObjectView):
    model = Part
    form_class = PartForm

    def form_valid(self, form):
        if self.object:
            old = Part.objects.get(id=self.object.id)
            self.object = form.save(commit=False)
            if self.object.price != old.price:
                self.object.price_date = date.today()
            self.object.save()
        else:
            self.object = form.save()
        return super().form_valid(form)

前端通过HTMX发起请求:

<div hx-target="this">
  <form method="post"
        hx-post="{{ hx_url }}"
        hx-on:htmx:validation:failed="this.reportValidity()"
        hx-trigger="click from:#btn-save">
    {% csrf_token %}
    {{ form.price }}
    {{ form.price_date }}
  </form>  
  {% include "btn_save.html" %}
</div>

遇到的问题

数据库中的price_date已成功更新,但HTMX返回的表单仍显示旧的price_date值,再次点击保存会覆盖之前的修改。


原因分析

核心问题出在表单实例的同步上:

  • 你在PartView的form_valid里手动更新了self.object的price_date并保存到数据库,但传递给父类form_valid的form实例还是修改前的旧对象,没有同步更新price_date字段的值。
  • 父类ObjectView直接用这个旧表单实例渲染响应,导致前端拿到的表单依旧显示修改前的price_date。

解决方案

有两种可行的修复方式:

方式一:同步更新表单实例的字段值

保存self.object后,直接更新传入的form实例的price_date值,确保渲染时使用最新数据:

class PartView(ObjectView):
    model = Part
    form_class = PartForm

    def form_valid(self, form):
        if self.object:
            old = self.object  # 优化:直接用已获取的实例,避免额外查询
            self.object = form.save(commit=False)
            if self.object.price != old.price:
                self.object.price_date = date.today()
                # 同步更新表单实例的对应字段
                form.instance.price_date = self.object.price_date
            self.object.save()
        else:
            self.object = form.save()
        return super().form_valid(form)

方式二:基于最新对象重新生成表单

在调用父类方法前,用更新后的self.object重新创建表单实例,替换原来的旧表单:

class PartView(ObjectView):
    model = Part
    form_class = PartForm

    def form_valid(self, form):
        if self.object:
            old = self.object  # 优化:避免额外数据库查询
            self.object = form.save(commit=False)
            if self.object.price != old.price:
                self.object.price_date = date.today()
            self.object.save()
            # 用更新后的对象重新生成表单
            form = self.form_class(instance=self.object)
        else:
            self.object = form.save()
        return super().form_valid(form)

内容的提问来源于stack exchange,提问作者Viktor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 23:27:45