Django & HTMX - 使表单 render_field 成为 HTMX 的目标

问题描述 投票:0回答:1

我创建了一个 django 表单,用户可以在其中输入客户端的部分名称。 HTMX 显示所有匹配的客户,当按下客户名称旁边的按钮时,我希望它填充多个表单字段。让我们考虑简化的 Django 手动表单示例:

发票/模板/invoice_add.html

{% extends 'base.html' %}
{% load widget_tweaks %}
{% block content %}
<form method='POST' autocomplete='off'> {% csrf_token %}
    <label>{{ form.number.label_tag }}</label>
    {{ form.number.errors }}
    {% render_field form.number class="form-control" %}
    <br>

    <label>{{ form.buyer_name.label_tag }}</label>
    {{ form.buyer_name.errors }}
    {% render_field form.buyer_name class="form-control" hx-post="/invoices/check_client/" hx-trigger="keyup" hx-target="#buyer_names_list" %}
    <div id="buyer_names_list"></div>
    <br>

    <label>{{ form.buyer_tax_no.label_tag }}</label>
    {{ form.buyer_tax_no.errors }}
    {% render_field form.buyer_tax_no class="form-control" %}
    <br><div id="tax_no_test"></div>

    <input type='submit' value='save'/>
</form>
{% endblock %}

如上所述,在填充

buyer_name
时,我会得到一个客户名称列表,其中
buyer_names_list
内的名称旁边有一个按钮。该按钮调用以下函数来提取税号:

发票/views.py

class InvoiceCreateView(CreateView):
    template_name: str = 'invoice_add.html'
    form_class = InvoiceForm
    queryset = Invoice.objects.all()

    def form_valid(self, form):
        return super().form_valid(form)


def particular_client_invoice(request):
    client_obj = Client.objects.all().filter(name=request.POST.get('clientname'))
    context = {'client_tax_no': client_obj.values_list('tax_no', flat=True)[0]}
    return render(request, 'partials/specific-invoice.html', context)

我的问题:

虽然它正确返回所需的税号,但我只能从 div 内的 HTMX 返回值(在本例中为

id="tax_no_test"
)。我希望字段
form.buyer_tax_no
成为税号的目标字段。那可能吗?或者(更糟糕的情况),可以通过另一种方式将该值添加到 POST 请求中,根本不需要显示
render_field

如果需要任何其他代码,请告诉我。预先感谢。

python django django-forms htmx
1个回答
0
投票

这将是我的首选方法。

hx-post
更改为
hx-get
并将其指向相同的视图。发出 htmx 请求时,应包含带有输入值的 url 查询。

然后重写视图的

get_initial
方法来设置字段的初始值(您还可以检查请求是否是 htmx 类型,只是为了确保):

def get_initial(self):
    initial = super().get_initial()

    if 'clientname' in self.request.GET:
        client_obj = Client.objects.all().filter(name=self.request.GET.get('clientname'))
        initial['buyer_tax_no'] = client_obj.values_list('tax_no', flat=True)[0]

    return initial

您将获得完整的 html 响应,您可以通过使用

buyer_tax_no
将其指向您的字段 ID 来检索
hx-select
字段。

目标将是相同的 id,但您可能需要将交换类型更改为 externalHTML(另一种方法是使用 div/span 包裹输入字段,并使用它来选择和定位元素)。

如果您只想返回包括字段在内的部分内容,则需要使用生成部分内容的内容(例如

django-render-block
django-template-partials)覆盖 render_to_response

方法

因此,您还需要处理提交表单导致完全刷新的情况,以防表单无效。


当然,可能还有其他一些方法来处理它,例如:

  • 仅调用url并使用js设置值
  • 使用仅渲染指定字段的专用视图

我的解决方案的原因是允许您重用已经存在的逻辑。

如果逻辑变得更复杂,我会考虑将视图重写为 FBV,但使用 CBV 时事情会变得非常疯狂和混乱;)

© www.soinside.com 2019 - 2024. All rights reserved.