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
相关产品推荐
相关产品推荐

