Django页面切换Select选项时出现重复渲染问题求助
Django切换Select选项时页面重复渲染问题解决
问题
用Django搭建网站,仅引入少量第三方插件。切换页面中Select选项时,页面出现重复渲染。修改htmx的hx-swap参数(如outer、innerHTML等)无法解决,反而恶化;自行编写AJAX实现相同逻辑,问题完全一致。
开发环境
Windows 11 Pro x64 Visual Studio Code x64 python 3.12.3 Packages Versions ------------------------ --------- asgiref 3.8.1 certifi 2025.1.31 charset-normalizer 3.4.1 Django 5.2 django-htmx 1.23.0 django-multiselectfield 0.1.13 django-phonenumber-field 8.1.0 idna 3.10 phonenumberslite 9.0.3 pip 24.0 pyasn1 0.6.1 pyasn1_modules 0.4.2 python-ldap 3.4.4
核心原因
视图函数create_ticket无论请求类型如何,都会返回完整的页面(包含导航栏、Select控件和表单)。而htmx或自定义AJAX是把完整页面内容塞进#form-content元素内,导致原页面的导航、Select等内容被重复插入,出现渲染重复问题。
解决方案
1. 创建表单片段模板
新建仅渲染表单内容的模板form_snippet.html:
<form name="form-content" id="form-content" method="post"> {% csrf_token %} {{ form }} <button type="submit" name="Create Ticket">Create Ticket</button> </form>
2. 修改视图函数,区分请求类型
利用django-htmx的request.htmx属性判断请求类型,返回对应模板:
from django.shortcuts import render, redirect from django_htmx.http import HttpResponseClientRedirect def create_ticket(request): form_selection = request.POST.get('select_ticket_type') if request.method == "POST": match form_selection: case "new_user": print("new user") new_user = CreateUser(request.POST) # 修正拼写错误:CreeateUser → CreateUser if new_user.is_valid(): request.session['display_form'] = form_selection # htmx请求用专用重定向响应 if request.htmx: return HttpResponseClientRedirect('createticket') return redirect('createticket') case "new_app": print("new app") new_app = CreateApplication(request.POST) if new_app.is_valid(): request.session['display_form'] = form_selection if request.htmx: return HttpResponseClientRedirect('my_view') return redirect('my_view') case "new_asset": print("new asset") new_asset = CreateAsset(request.POST) # 补充漏传的request.POST参数 if new_asset.is_valid(): request.session['display_form'] = form_selection if request.htmx: return HttpResponseClientRedirect('my_view') return redirect('my_view') case _: print("other") form = CreateOther(request.POST) # 确定要展示的表单 display_form = request.session.get('display_form', form_selection) print(f"display form is {display_form}") match display_form: case "new_user": form = CreateUser() case "new_app": form = CreateApplication() case "new_asset": form = CreateAsset() case _: form = CreateOther() context = {'form': form} # 根据请求类型返回不同模板 if request.htmx: return render(request, 'website/form_snippet.html', context) return render(request, 'website/createticket.html', context)
3. 保留原htmx配置
原Select控件的htmx属性无需调整,保持即可:
<select hx-post="/createticket/" hx-swap="innerHTML" hx-trigger="change" hx-target="#form-content" selected="other" name="select_ticket_type" id="select_ticket_type"> <option value="new_user">New Employee</option> <option value="new_asset">New Asset</option> <option value="new_app">New Application</option> <option value="other">Other</option> </select>
4. 自定义AJAX的调整(可选)
如果继续使用自定义AJAX,只需确保视图返回片段内容,原有AJAX逻辑保持不变即可。
内容的提问来源于stack exchange,提问作者Echo
相关产品推荐
相关产品推荐

