【问题标题】:How to access run-time request.session values in forms.py definition?如何访问 forms.py 定义中的运行时 request.session 值?
【发布时间】:2018-05-25 14:58:57
【问题描述】:

我有一个库存管理应用,它将服务于多个位置(在我的应用中称为上下文)。当用户登录时,他们当前的上下文作为值存储在 request.sessions 中。

我希望用户只能浏览和检索他们自己位置的记录。

我一直在尝试通过过滤表单定义中调用的查询集来填充选择下拉列表,即

    referenced_catalog = forms.ModelChoiceField(
    queryset=Inventory_unit_catalog.objects.all().filter(parent_business_unit_context_id=user_context_id),

我已经尝试从各种 SO 帖子中实现几种不同(但相似)的方法,其中涉及为表单定义一个 init 块,例如:

class InventoryStockAddForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user_context_id = kwargs.pop('user_context_id', None)
        super(InventoryStockAddForm, self).__init__(*args, **kwargs)

    name = forms.CharField(max_length=96,widget=forms.TextInput(),required=True)

    referenced_catalog = forms.ModelChoiceField(
        queryset = Inventory_unit_catalog.objects.all().filter(parent_business_unit_context_id=self.user_context_id),
        label = u"",
        widget = ModelSelect2Widget(
            model=Inventory_unit_catalog,
            search_fields=['name__icontains'],
            attrs={'data-placeholder': 'Select catalog...', 'data-width': '35em'},
        required=False))

    class Meta():
        model = Inventory_unit_stock
        fields = ('name',)

(不同的 SO 答案有一种或另一种。)

然后在views.py中:

user_context_id = request.session.get('user_context_id')
...
add_form = InventoryStockAddForm(user_context_id=user_context_id)

我什至尝试使用https://djangobook.com/using-sessions-views-2/ 的 SessionStore:

SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
s = SessionStore()
user_context_id = s['user_context_id']

但它总是在forms.py更新时失败,因为Django验证代码并且在验证时找不到键值。

任何建议将不胜感激,谢谢!

【问题讨论】:

  • @Alasdair 已根据您的要求更新。
  • 请检查缩进
  • @Alasdair,已更正,感谢您指出

标签: django


【解决方案1】:

您无法在referenced_catalog = forms.ModelChoiceField(...) 中访问self.user_context_id - 该代码在模块加载时运行,而不是在表单初始化时运行。

相反,您应该在 __init__ 方法中设置查询集。

class InventoryStockAddForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user_context_id = kwargs.pop('user_context_id', None)
        super(InventoryStockAddForm, self).__init__(*args, **kwargs)
        self.fields['referenced_catalog'].queryset = Inventory_unit_catalog.objects.all().filter(parent_business_unit_context_id=self.user_context_id)

    referenced_catalog = forms.ModelChoiceField(
        queryset = Inventory_unit_catalog.objects.none(),
        label = u"",
        widget = ModelSelect2Widget(
            model=Inventory_unit_catalog,
            search_fields=['name__icontains'],
            attrs={'data-placeholder': 'Select catalog...', 'data-width': '35em'},
        required=False))

【讨论】:

  • 谢谢!尽管为了澄清,我不得不将整个 referenced_catalog 字段定义移动到 init 中,否则该定义将无法访问查询集,原因与您强调的相同。太棒了!
  • 不,您不需要将整个字段定义移动到__init__。字段定义使用使用.none() 的空查询集。然后您可以覆盖__init__ 中的查询集,您可以在其中访问self.user_context_id
  • 你是对的,我的错误 - 我阅读了您的解决方案并在没有仔细查看您发布的代码更改的情况下实施它。如果你按照自己的方式行事,它会很好地工作!如果将整个定义移入,该字段的其他方面(它是 django-select2 字段)将无法正确初始化。
  • 我看不出初始化__init__ 中的字段会如何破坏select2,但很高兴上面的代码对你有用。
  • 再次感谢您的帮助。最后,您的更正回答了我的具体问题(将变量“降低”到查询集可以访问它的位置)。然而,事实证明这是徒劳的,因为查询集似乎被忽略了——无论是 .all()、.none() 还是其他任何东西,交付的结果始终是所有项目。更多信息请参见 [链接] (stackoverflow.com/questions/50575382/…)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 2012-01-28
  • 1970-01-01
  • 2011-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多