【问题标题】:Accessing request object in django urls.py在 django urls.py 中访问请求对象
【发布时间】:2020-11-04 00:25:22
【问题描述】:

这个问题也受到文档here的启发。

我在 Django 中使用通用视图 (ListView) 来列出当前登录用户提出的所有问题。我很好奇不用在views.py 中创建视图就可以做到这一点。所以在 urls.py 我添加了如下路径:

urlpatterns += [
    path('myqn/', login_required(views.ListView.as_view(model=models.Question, queryset=models.Question.objects.filter(user__id=request.user.id), template_name='testapp/question_list.html', context_object_name='questions')), name='myqn'),
]

它给了我:

NameError: name 'request' 未定义

我知道。因为,请求对象由 URLConf 传递给 View 类/函数。那么,有没有办法,我可以在这个范围内访问 user.id。

PS:如果我替换 user__id=9,代码就可以工作。它列出了用户 9 提出的所有问题。 :)

【问题讨论】:

    标签: python django django-views django-generic-views


    【解决方案1】:

    您通常通过覆盖ListView子类 中的get_queryset 方法来做到这一点。所以你可以创建一个视图:

    # app/views.py
    
    from django.contrib.auth.mixins import LoginRequiredMixin
    from django.views.generic.list import ListView
    from app.models import Question
    
    class QuestionListView(LoginRequiredMixin, ListView):
        model = Question
        template_name='testapp/question_list.html'
        context_object_name='questions'
    
        def get_queryset(self, *args, **kwargs):
            return super().get_queryset(*args, **kwargs).filter(
                user_id=self.request.user.id
            )

    然后在urls.py 中使用QuestionListView

    # app/urls.py
    
    from django.urls import path
    from app.views import QuestionListView
    
    urlpatterns += [
        path('myqn/', QuestionListView.as_view(), name='myqn'),
    ]

    您可以使用以下方法定义函数或 lambda 表达式:

    import inspect
    
    def custom_queryset(*args, **kwargs):
        self = inspect.currentframe().f_back.f_locals['self']
        return Question.objects.filter(
            user_id=self.request.user.id
        )
    
    urlpatterns += [
        path('myqn/', QuestionListView.as_view(get_queryset=custom_queryset), name='myqn'),
    ]

    然而,这不是一个好主意。首先,它会检查调用堆栈,如果稍后ListView 被更改,它可能不再起作用。此外,此列表视图不会检查用户是否已登录。我们不能使用方法解析顺序 (MRO) 来调用 super() 方法。


    注意:您可以将视图限制为基于类的视图,以向经过身份验证的用户提供 LoginRequiredMixin mixin [Django-doc].

    【讨论】:

    • 感谢您的回答。我知道我可以这样做。但我想知道是否可以在不在views.py中创建类的情况下完成它
    • @Pax:我不明白为什么创建一个新类是个问题?
    • 它们的工作原理几乎相同。但是,为了最小化views.py 中的代码,我正在学习一种在我的urls.py 中写入的方法。所以也许以后如果我用假设日期和其他创建查询集过滤器,我可能不需要填充我的views.py。简单来说:只是为了快速开发:)
    • @Pax: 但是你仍然可以在QuestionListView.as_view 中添加额外的属性,所以如果你真的想要这个,你可以制作一些OwnerListView 过滤user_id ,然后例如使用OwnerListView.as_view(model=Question)。通常,放置这么多细节并不是一个好主意。事实上,ListViews 等很少这样做。您可能可以使用 lambda 表达式,但这会非常混乱,而且在您无法使用 MRO 的意义上“不稳定” super() 分辨率。
    • 非常感谢。如果可以,请添加带有这些不稳定细节的 lambda 示例。所以我可以接受这个答案作为解决方案
    【解决方案2】:

    不,你不能。

    as_view() 接受视图类的任何类属性。在您的情况下,该类将无法访问 request 对象

    class Foo(ListView):
        queryset = Question.objects.filter(user__id=request.user.id)

    上面的 sn-p 你不能引用request,因此也不能引用你的urls.py

    如您所知,在这些复杂情况下,我们应该覆盖get_queryset()

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 2016-11-08
      • 2012-01-28
      • 2014-07-20
      • 1970-01-01
      • 2011-11-15
      • 2011-06-17
      相关资源
      最近更新 更多