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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 10:55:53