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

Django表单获取模型ID失败及ArtistForm加载性能优化求助

Django 表单数据传递与性能优化问题

一、表单传递名称而非ID,无法正确关联SpotifyData模型

问题分析

现有表单(如ChartForm、Artist1Form)中,ChoiceField的选项用values_list("name","name")生成,导致表单提交的是模型的name字符串而非ID。视图中尝试通过chart["name"]获取名称是错误的——request.GET.get("CHART")返回的是字符串,不是字典;同时,通过名称查询模型再获取ID的方式冗余且容易出错。

解决方案

修改表单,让ChoiceField的选项绑定模型ID作为值,显示名称作为选项文本:

修改forms.py中的表单

class Artist1Form(forms.Form):
    ARTIST = forms.ChoiceField(required=True, widget=forms.Select,)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 用(id, name)生成选项,值为ID,显示为名称
        self.fields['ARTIST'].choices = Artist.objects.values_list("id", "name")

class ChartForm(forms.Form):
    CHART = forms.ChoiceField(required=True, widget=forms.Select,)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['CHART'].choices = Chart.objects.values_list("id", "name")

class RegionForm(forms.Form):
    REGION = forms.ChoiceField(required=True, widget=forms.Select,)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['REGION'].choices = Region.objects.values_list("id", "name")

修改views.py中的查询逻辑

直接使用提交的ID过滤关联模型,无需额外查询:

def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
    context = super().get_context_data(**kwargs)

    start = self.request.GET.get("FROM")
    end = self.request.GET.get("TO")
    artist_id = self.request.GET.get("ARTIST")  # 现在获取的是ID
    title = self.request.GET.get("TITLE")
    region_id = self.request.GET.get("REGION")
    chart_id = self.request.GET.get("CHART")

    # 直接用ID过滤关联模型
    data_filtered = SpotifyData.objects.filter(
        date__range=(start, end),
        artist_id=artist_id,
        title__name=title,  # 若需更精准匹配,可修改表单传递Title的ID
        region_id=region_id,
        chart_id=chart_id
    ).values()

    data = data_filtered.values_list("date", "rank")
    fig = make_song_rank_changes_chart(data, start, end, artist, title)
    chart = fig.to_html()

    context = {
        "chart": chart,
        "daterange_form": DateRangeForm(),
        "artist1_form": Artist1Form(),
        "title1_form": Title1Form(),
        "chart_form": ChartForm(),
        "region_form": RegionForm(),
        "df": data_filtered             
    }

    return context

注意:如果需要按Title精准匹配,建议修改表单传递Title的ID,避免因重名导致查询错误。

二、Artist模型数据量过大导致表单加载性能极差

问题分析

Artist模型有9万条数据,用ChoiceField加载所有选项会生成大量<option>标签,导致页面渲染缓慢甚至浏览器崩溃。

解决方案

替换ChoiceField为AJAX自动补全组件,动态加载匹配的选项,避免一次性加载所有数据:

1. 修改forms.py

将ChoiceField改为CharField,添加用于JS绑定的属性:

class Artist1Form(forms.Form):
    ARTIST = forms.CharField(
        required=True,
        widget=forms.TextInput(attrs={
            'class': 'artist-autocomplete',
            'placeholder': '输入艺术家名称搜索'
        })
    )
    # 添加隐藏字段存储选中的艺术家ID
    ARTIST_ID = forms.CharField(widget=forms.HiddenInput(), required=False)

2. 添加AJAX搜索视图

# views.py
from django.http import JsonResponse
from .models import Artist

def artist_autocomplete(request):
    query = request.GET.get('q', '')
    # 只返回前20条匹配结果,避免数据过多
    artists = Artist.objects.filter(name__icontains=query)[:20]
    results = [{'id': artist.id, 'text': artist.name} for artist in artists]
    return JsonResponse({'results': results})

3. 添加路由

# urls.py
from django.urls import path
from .views import artist_autocomplete

urlpatterns = [
    # 其他路由...
    path('artist-autocomplete/', artist_autocomplete, name='artist-autocomplete'),
]

4. 模板中添加自动补全JS逻辑

(需引入jQuery和jQuery UI库,建议通过本地静态文件加载)

<script>
$(document).ready(function() {
    $('.artist-autocomplete').autocomplete({
        source: '/artist-autocomplete/',
        minLength: 2,  // 输入至少2个字符触发搜索
        select: function(event, ui) {
            // 选中后将ID存入隐藏字段
            $(this).siblings('[name="ARTIST_ID"]').val(ui.item.id);
        }
    });
});
</script>

也可使用django-autocomplete-light库,它提供了更便捷的自动补全实现,无需手动编写大量JS代码。

内容的提问来源于stack exchange,提问作者Damian Bylicki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 06:15:44