如何通过HTMX从事件获取数据?标签删除同步会话列表问题
问题与解决方案
问题背景
我有如下视图用于删除标签,运行正常:
def tag_delete(request): if request.method == 'POST': tag_name = request.POST.get("tag") tag = Tag.objects.get(name=tag_name) tag.delete() response = HttpResponse(status=204, headers={'HX-Trigger': json.dumps({ "taglistchangeddelete": {"tag": tag_name} })}) return response
但需要同步移除会话变量selected_tags中的已删除标签,因此创建了处理视图:
def process_tags_deleted(request, tag): selected_tags = request.session['selected_tags'] if tag in selected_tags: selected_tags.remove(tag) request.session['selected_tags'] = selected_tags # 渲染模板展示用户的选中标签 response = render(request, 'espace/tags_selected.html', { 'selected_tags': selected_tags, }) return response
在模板中用HTMX设置GET请求触发该视图时,控制台出现htmx:syntax:error,无法从taglistchangeddelete事件中获取tag值:
<div hx-get={% url 'process_tags_deleted' %} hx-vals='{"tag": evt.detail.tag}' hx-target="#tags_selected" hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' hx-trigger="taglistchangeddelete"> </div>
错误原因
htmx:syntax:error是因为**hx-vals的写法不符合HTMX语法规则**:直接在JSON字符串中写入JS变量evt.detail.tag,HTMX无法解析这种格式,必须使用HTMX支持的表达式写法。
修复方案
1. 修正hx-vals的写法
有两种合法的写法可以从事件中取值:
方式一:使用javascript:前缀执行JS表达式
<div hx-get="{% url 'process_tags_deleted' %}" hx-vals='javascript: {tag: evt.detail.tag}' hx-target="#tags_selected" hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' hx-trigger="taglistchangeddelete"> </div>
方式二:使用HTMX模板语法包裹变量
<div hx-get="{% url 'process_tags_deleted' %}" hx-vals='{"tag": "{{ evt.detail.tag }}"}' hx-target="#tags_selected" hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}' hx-trigger="taglistchangeddelete"> </div>
2. 修正视图的参数接收逻辑
原视图将tag作为位置参数,但HTMX GET请求会把参数放在查询字符串中,需要修改视图从request.GET获取参数,同时增加异常处理避免KeyError:
def process_tags_deleted(request): tag = request.GET.get("tag") if not tag: return HttpResponseBadRequest() # 确保会话中存在selected_tags,不存在则返回空列表 selected_tags = request.session.get('selected_tags', []) if tag in selected_tags: selected_tags.remove(tag) request.session['selected_tags'] = selected_tags return render(request, 'espace/tags_selected.html', { 'selected_tags': selected_tags, })
3. 更新URL配置
去掉URL中的tag位置参数,示例如下:
# urls.py from django.urls import path from . import views urlpatterns = [ # ... 其他URL path('process-tags-deleted/', views.process_tags_deleted, name='process_tags_deleted'), ]
内容的提问来源于stack exchange,提问作者Isaac Fritsch
相关产品推荐
相关产品推荐

