如何在Django中获取GET请求的值?

624
我目前正在定义正则表达式,以便捕获URL中的参数,就像教程中描述的那样。我如何从URL中访问参数,作为HttpRequest对象的一部分?
我的HttpRequest.GET目前返回一个空的QueryDict对象。
我想学习如何在没有库的情况下做到这一点,这样我就可以更好地了解Django。
19个回答

844

当URL类似于domain/search/?q=haha时,您可以使用request.GET.get('q', '')

q是您想要的参数,而''是如果未找到q的默认值。

然而,如果您只是在配置URLconf**,那么从regex捕获的内容将作为参数(或命名参数)传递给函数。

例如:

(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),

然后在您的views.py中,您将拥有:

def profile_page(request, username):
    # Rest of the method

13
“?param=”是Django识别参数的唯一方式吗?是否有一种方法可以使用URLconf和HTTP.GET一起使用?我想要实现/param/2的效果。 - sutee
3
请查看我回复的第二部分,关于您的URLconf和正则表达式捕获。 - camflan
2
没问题。如果你使用 GET 提交表单,就用 request.GET;如果你使用 POST 提交表单,就用 request.POST;如果你只想配置 URL 有变量部分,那么就是 URLconf/view 参数。 - camflan
14
类视图怎么样? - User
25
对于基于类的视图,您可以使用self.kwargs['parameter'] - Royendgel Silberie
显示剩余5条评论

441

为了澄清camflan解释,假设您有:

  • 规则url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
  • 一个传入请求:http://domain/user/thaiyoshi/?message=Hi

URL分发器规则将捕获 URL 路径 的部分(此处是"user/thaiyoshi/"),并将它们与请求对象一起传递给视图函数。

查询字符串(这里是message=Hi)会被解析成参数,并在request.GET中作为QueryDict存储。不会对HTTP GET参数进行进一步匹配或处理。

这个视图函数将使用从URL路径提取出来的部分和一个查询参数:

def profile_page(request, username=None):
    user = User.objects.get(username=username)
    message = request.GET.get('message')

顺便提一下,在这种情况下,您可以在request.method中找到请求方法(在本例中为"GET",对于提交的表单通常为"POST")。 在某些情况下,检查它是否与您期望的相匹配会很有用。

更新:当决定使用URL路径还是查询参数传递信息时,以下内容可能有所帮助:

  • 使用URL路径唯一标识资源,例如/blog/post/15/(而不是/blog/posts/?id=15
  • 使用查询参数更改显示资源的方式,例如/blog/post/15/?show_comments=1/blog/posts/2008/?sort_by=date&direction=desc
  • 为了创建用户友好的URL,避免使用ID号码,而使用日期、类别和/或缩略语:/blog/post/2008/09/30/django-urls/

30
这是一篇写得非常好的答案。它确实帮助我更好地理解了Django。 - Mark
2
如何在不指定名称的情况下获取所有参数值? - numerah
@numerah,request.GET是一个Python字典。你可以通过request.GET.items()进行迭代。 - akaihola
1
有什么原因可以解释为什么最好遵循更新中写的习惯?(何时使用URL路径与GET参数) - m0etaz
@m0etaz 真的是一个很好的问题。我认为你会很难找到这个概念的起源。从我的经验来看,这是以一种几乎部落式的方式传承给我的,我也很想知道它的起源。 - Derek Adair

83

使用 GET 方法

request.GET["id"]

使用POST

request.POST["id"]

47
尽管这对于已有的键有效,但是camflan和akaihola提供的答案使用.get()来避免在缺失键时出现KeyError异常。做同样的事情是明智的(例如,request.POST.get('id', ''))。 - vastlysuperiorman

66

有人会想知道如何在文件urls.py中设置路径,例如:

domain/search/?q=CA

这样我们就可以调用查询。

事实上,在文件urls.py中设置这样的路由并不是必要的。你只需要在urls.py中设置路由:

urlpatterns = [
    path('domain/search/', views.CityListView.as_view()),
]

当您输入http://servername:port/domain/search/?q=CA时,查询部分“?q=CA”将自动保留在散列表中,您可以通过该散列表进行引用。

request.GET.get('q', None).

这是一个示例(文件views.py

class CityListView(generics.ListAPIView):
    serializer_class = CityNameSerializer

    def get_queryset(self):
        if self.request.method == 'GET':
            queryset = City.objects.all()
            state_name = self.request.GET.get('q', None)
            if state_name is not None:
                queryset = queryset.filter(state__name=state_name)
            return queryset

此外,当您在URL中编写查询字符串时:

http://servername:port/domain/search/?q=CA
不要将查询字符串用引号括起来。例如,
http://servername:port/domain/search/?q="CA"

嗨,Eric!我是Django的新手。你能不能详细解释一下 "queryset = queryset.filter(state__name=state_name)" 这个语句的含义? 双下划线"__"在 "state__name" 中有什么意义? - Subbu
1
这里的“state”是一个表,而“name”是该表中的一个字段。在Django的过滤器中,state__name将引用“state”表中“name”字段的值。 - Eric Andrews

33
def some_view(request, *args, **kwargs):
    if kwargs.get('q', None):
        # Do something here ..

31

如果你只有request对象的情况,你可以使用request.parser_context['kwargs']['your_param']


27

如果你的URL长这样,你有两种常用的方法来做到这一点:

https://domain/method/?a=x&b=y

版本 1:

如果某个特定键是必需的,您可以使用:

key_a = request.GET['a']

如果该键存在,则返回值a,否则返回异常

版本2:

如果您的键是可选的:

request.GET.get('a')

你可以尝试不带任何参数运行这个代码,它不会崩溃。 所以你可以用try: except:包装它,并在示例中返回HttpResponseBadRequest()。 这是一种简单的方法,可以使你的代码更简洁,而无需使用特殊的异常处理。


我怎样在模板中检测查询参数? - Akin Hwan

17

我想分享一个小技巧,可能可以节省您的时间。
如果您计划在urls.py文件中使用类似以下的内容:

url(r'^(?P<username>\w+)/$', views.profile_page,),

这基本上意味着www.example.com/<username>。请确保将其放置在URL条目的末尾,否则它容易与以下的URL条目发生冲突,即访问它们之一会给您带来一个美好的错误提示:User matching query does not exist.

我自己刚刚经历了这个问题;希望它能有所帮助!


2
此外,在这种情况下,您可能需要检查用户名称是否与其他网址条目发生冲突。 - DrKaoliN

12

目前这些查询有两种方式。如果您想访问查询参数(GET),则可以查询以下内容:

http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1

如果您想访问通过POST传递的参数,需要按照以下方式访问:

request.data.get('role', None)

使用 'get()' 访问字典(QueryDict)时,您可以设置默认值。在上述情况中,如果未提供 'status' 或 'role' 的值,则为 None。


11
如果你不知道参数的名称并且想要处理它们所有,可以使用request.GET.keys()dict(request.GET)函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接