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

如何为Django Form ChoiceField传递company_id参数实现数据库过滤查询

Django Form动态传递company_id过滤ChoiceField选项的解决方案

你的现有代码存在两个核心问题:

  • 数据库查询写在类顶层,属于类属性初始化逻辑,会在类加载时执行,此时company_id还未通过__init__传入,根本无法获取到正确的参数;
  • 使用字符串拼接SQL语句,存在SQL注入风险,非常不安全。

以下是修正后的完整实现:

修正后的forms.py

from django import forms
import db

class NewColumn(forms.Form):
    # 先定义ChoiceField,初始设置空选项
    engine_choices = forms.ChoiceField(
        choices=[],
        help_text='Make your Choice'
    )

    def __init__(self, *args, **kwargs):
        # 取出传入的company_id,再调用父类初始化方法
        company_id = kwargs.pop('company_id')
        super().__init__(*args, **kwargs)
        
        # 在实例化阶段执行数据库查询,此时能获取到正确的company_id
        engine = db.engine("Database")
        # 使用with语句自动管理连接和游标,避免资源泄漏
        with engine.raw_connection() as connection:
            with connection.cursor() as cursor:
                # 用参数化查询替代字符串拼接,彻底避免SQL注入
                cursor.execute("SELECT id, name FROM table WHERE id = %s;", (company_id,))
                all_rows = cursor.fetchall()
        
        # 动态为ChoiceField设置过滤后的选项
        self.fields['engine_choices'].choices = [(row[0], row[1]) for row in all_rows]

views.py无需修改

你的views代码已经正确完成了company_id的传递,保持原样即可:

if request.method == 'GET':
    company_id = 1
    site_id = 3
    
    return render(request, 'sites/new-column.html',
                 {
                     'company_id': company_id,
                     'site_id': site_id,
                     'form_newcolumn': NewColumn(company_id),
                 })

关键改动说明

  • 查询逻辑移至__init__方法:类顶层代码仅在类加载时执行一次,而__init__在每次实例化表单时都会运行,确保每次都能根据传入的company_id动态查询数据;
  • 参数化查询防注入:用占位符替代字符串拼接,将company_id作为参数传入execute,避免恶意SQL注入;
  • 自动管理数据库资源:通过with语句自动关闭游标和连接,避免资源泄漏;
  • 动态设置字段选项:通过self.fields['字段名'].choices修改选项,保证每次实例化表单都加载对应公司的专属数据。

可选优化

  • 如果查询结果为空,可以设置默认选项,比如[(None, '暂无可用选项')];
  • 建议添加数据库异常捕获,避免因连接失败或查询错误导致表单初始化崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 00:35:20