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

如何在Django的forms.py中获取运行时request.session的值?

解决Django表单动态过滤QuerySet的验证错误问题

我来帮你梳理下问题所在,然后给出可行的解决方案:

1. 表单字段定义位置错误

你在__init__方法里重新定义了name和referenced_catalog字段,这会打乱Django的表单验证流程——表单字段应该定义在类级别,而非初始化方法内部。正确的做法是先在类里声明字段,再在__init__中修改referenced_catalog的queryset。

2. Meta类未包含所需字段

你的Meta类中fields只指定了('name',),但表单实际还有referenced_catalog字段,这会导致该字段不被表单识别,进而引发验证或渲染异常。

3. SessionStore使用错误

你新建了一个空的SessionStore实例,自然找不到user_context_id。应该直接使用当前请求的request.session来获取会话数据,就像你最初尝试的那样。

修正后的完整代码

forms.py

from django import forms
from .models import Inventory_unit_stock, Inventory_unit_catalog
from dal import ModelSelect2Widget

class InventoryStockAddForm(forms.ModelForm):
    # 在类级别声明所有字段
    name = forms.CharField(
        max_length=96,
        widget=forms.TextInput(),
        required=True
    )
    referenced_catalog = forms.ModelChoiceField(
        queryset=Inventory_unit_catalog.objects.none(),  # 初始化为空QuerySet,后续动态更新
        label="",
        widget=ModelSelect2Widget(
            model=Inventory_unit_catalog,
            search_fields=['name__icontains'],
            attrs={'data-placeholder': 'Select catalog...', 'data-width': '35em'}
        ),
        required=False
    )

    def __init__(self, *args, **kwargs):
        # 取出user_context_id并设置默认值,避免KeyError
        self.user_context_id = kwargs.pop('user_context_id', None)
        super().__init__(*args, **kwargs)
        
        # 仅当user_context_id有效时,过滤QuerySet
        if self.user_context_id:
            self.fields['referenced_catalog'].queryset = Inventory_unit_catalog.objects.filter(
                parent_business_unit_context_id=self.user_context_id
            )

    class Meta:
        model = Inventory_unit_stock
        fields = ('name', 'referenced_catalog')  # 包含所有需要的字段

views.py

def your_stock_add_view(request):
    # 从当前请求的session获取值,设置默认值避免KeyError
    user_context_id = request.session.get('user_context_id')
    
    # 处理user_context_id不存在的情况(比如引导用户选择上下文)
    if not user_context_id:
        # 这里可根据业务逻辑处理,例如:
        # return redirect('context_selection_page')
        pass
    
    add_form = InventoryStockAddForm(user_context_id=user_context_id)
    
    # 后续的渲染或表单提交处理逻辑
    # ...

关键说明

  • 初始queryset设为objects.none():避免Django在验证表单类时,因缺少user_context_id而抛出错误。
  • 动态更新queryset:确保只有在表单实例化时,才根据用户的上下文过滤数据。
  • 给user_context_id设置默认值:无论是从session获取还是传递给表单,都用默认值兜底,避免KeyError。
  • Meta类包含所有字段:确保表单能正确识别并处理referenced_catalog字段。

这样修改后,应该就能解决你遇到的验证错误和键值找不到的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:48:20