我创建了一个 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
。
如果需要任何其他代码,请告诉我。预先感谢。
这将是我的首选方法。
将
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
方法
因此,您还需要处理提交表单导致完全刷新的情况,以防表单无效。
当然,可能还有其他一些方法来处理它,例如:
我的解决方案的原因是允许您重用已经存在的逻辑。
如果逻辑变得更复杂,我会考虑将视图重写为 FBV,但使用 CBV 时事情会变得非常疯狂和混乱;)