【问题标题】:pass request.user into form with ModelMultipleChoiceField , Django使用 ModelMultipleChoiceField 将 request.user 传递给表单,Django
【发布时间】:2019-09-29 16:01:33
【问题描述】:

我想将 request.user 或 request.user.pk 从基于类的视图传递到 ModelForm 以过滤使用 request.user.pk 设置的查询。 我有以下看法:


class ArticleResurrectionView(MessageLoginRequiredMixin, FormView):
    model = Article
    form_class = ArticleResurrectionForm
    template_name = "articles/resurrection.html"
    success_url = reverse_lazy("articles:articles_main")
    redirect_message = "You have to be logged in to recover articles "

    def get_form_kwargs(self):
        kwargs = FormView.get_form_kwargs(self)
        kwargs["author_id"] = self.request.user.pk
        return kwargs

def get_form_kwargs(self): 应该将 self.request.user.pk 作为 kwargs["author_id"] 传递给表单的 init

然后我有这个视图的以下表格:

class ArticleResurrectionForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.author_id = kwargs.pop("author_id", None)
        forms.ModelForm.__init__(self, *args, **kwargs)


    title = forms.ModelMultipleChoiceField(label="Deleted articles", 

help_text="Please select the    article to recover", 

queryset=Article.default.filter(show=False, author=???) )

# I can not use self.author_id  here

目标是在标题中使用 init 中的 self.author_id 来过滤查询集,以显示仅由当前用户创建的条目。换句话说,我需要在 title 的查询集中传递 self.author_id。

也许可以通过这样的方式来做到这一点:

def __init__(self, *args, **kwargs):
        self.author_id = kwargs.pop("author_id", None)
        forms.ModelForm.__init__(self, *args, **kwargs)
        self.fields[“title"].queryset = ???

无论如何,如果您知道如何在查询集中获取 request.user - 我很乐意为您提供解决方案。 谢谢!

关于相关管理器的 p.s:“默认”而不是标准“对象”,我使用 2 个管理器:


class ArticleManager(models.Manager):
    """Shows only non deleted articles"""
    def get_queryset(self):
        return models.Manager.get_queryset(self).exclude(show=False)


class Article(models.Model):
    # related managers
    default = models.Manager() # shows all articles
    objects = ArticleManager() # shows only non deleted articles
.....
.....
.....

【问题讨论】:

    标签: django django-forms


    【解决方案1】:

    将 request.user 添加到您的表单实例

    form = FormItemForm(request.POST or None, request.user)

    然后在你的 form.py 中添加这个

    field = forms.ModelMultipleChoiceField(
            widget=forms.CheckboxSelectMultiple,
            queryset=Field.objects.none(),
            label='Fields',
            help_text='Please select a field.'
        )
    
    def __init__(self, *args, **kwargs):
            us = args[1] or None
            forms.ModelForm.__init__(self, *args, **kwargs)
            self.fields['field'].queryset = Field.objects.filter(user=us)
    

    试试看它是否有效。对我来说效果很好。

    【讨论】:

      【解决方案2】:

      您的第二种方法确实是正确的,尽管您可能希望使用ModelChoiceField [Django-doc] 而不是ModelMultipleChoiceField [Django-doc],因为后者允许您选择多个,例如Articles,但是您的表单逻辑 (title) 暗示它是单数的。

      class ArticleResurrectionForm(forms.ModelForm):
      
          title = forms.ModelChoiceField(
              queryset=Article.objects.none()
              label='Deleted articles',
              help_text='Please select the article to recover'
          )
      
          def __init__(self, *args, **kwargs):
              author_id = kwargs.pop("author_id", None)
              forms.ModelForm.__init__(self, *args, **kwargs)
              self.fields['title'].queryset = Article.objects.filter(
                  author_id=author_id,
                  show=False
              )

      因此,我们最初将查询集指定为空,但后来通过在表单的构造函数中指定另一个查询集来修补它。

      至于您的观点,您可能希望进行super() 调用,而不是调用特定类的方法,例如:

      class ArticleResurrectionView(MessageLoginRequiredMixin, FormView):
      
          # ...
      
          def get_form_kwargs(self):
              kwargs = super().get_form_kwargs()
              kwargs['author_id'] = self.request.user.pk
              return kwargs

      【讨论】:

      • 谢谢你的回答,但它说:TypeError: __init__() missing 1 required positional argument: 'queryset'
      • @AlekseiKhatkevich:你能用 full 回溯编辑你的问题吗?
      • @AlekseiKhatkevich:我想我找到了问题所在。在答案中修复它。
      • 它有帮助,感谢您的帮助和时间。我不喜欢使用 super() 方法,因为在我的选择中它比直接类调用更显式。另一方面,它更像是口味的选择。我使用 ModelMultipleChoiceField 一次恢复几篇文章
      • 在这种情况下 DEBUGTOOL 不跟踪 SQL 事务也很奇怪,但无论如何它都可以工作......只是奇怪......
      猜你喜欢
      • 2020-05-08
      • 2011-11-20
      • 1970-01-01
      • 2020-07-22
      • 2010-12-31
      • 2011-04-01
      • 1970-01-01
      • 2020-04-13
      • 2016-08-07
      相关资源
      最近更新 更多