【问题标题】:Django: simulate HTTP requests in shellDjango:在 shell 中模拟 HTTP 请求
【发布时间】:2012-07-30 04:54:48
【问题描述】:

我刚刚了解到,使用 Rails 可以在控制台中用几行代码模拟 HTTP 请求。

查看:http://37signals.com/svn/posts/3176-three-quick-rails-console-tips(“深入了解您的应用”部分)。

有没有类似的方法可以用 Django 做到这一点?会很方便。

【问题讨论】:

    标签: django django-shell


    【解决方案1】:

    您可以使用RequestFactory,它允许

    • 将用户插入到请求中

    • 将上传的文件插入到请求中

    • 向视图发送特定参数

    并且不需要使用requests的额外依赖。

    请注意,您必须同时指定 URL 和视图类,因此与使用请求相比,它需要多行代码。

    from django.test import RequestFactory
    
    request_factory = RequestFactory()
    my_url = '/my_full/url/here'  # Replace with your URL -- or use reverse
    my_request = request_factory.get(my_url)
    response = MyClasBasedView.as_view()(my_request)  # Replace with your view
    response.render()
    print(response)
    

    要设置请求的用户,请在获得响应之前执行my_request.user = User.objects.get(id=123) 之类的操作。

    要将参数发送到基于类的视图,请执行response = MyClasBasedView.as_view()(my_request, parameter_1, parameter_2) 之类的操作

    扩展示例

    这是一个将RequestFactory 与这些东西结合使用的示例

    • HTTP POST(到 url url、功能视图 view 和数据字典 post_data

    • 上传单个文件(路径file_path,名称file_name,表单字段值file_key

    • 为请求分配用户 (user)

    • 从 url (url_kwargs) 传递 kwargs 字典

    SimpleUploadedFile 帮助以对表单有效的方式格式化文件。

    from django.core.files.uploadedfile import SimpleUploadedFile
    from django.test import RequestFactory
    
    request = RequestFactory().post(url, post_data)
    with open(file_path, 'rb') as file_ptr:
        request.FILES[file_key] = SimpleUploadedFile(file_name, file_ptr.read())
        file_ptr.seek(0)  # resets the file pointer after the read
        if user:
            request.user = user
        response = view(request, **url_kwargs)
    

    在 Python shell 中使用 RequestFactory

    RequestFactory 默认情况下将您的服务器命名为“testserver”,如果您不在测试代码中使用它可能会导致问题。您会看到如下错误:

    DisallowedHost: Invalid HTTP_HOST header: 'testserver'. You may need to add 'testserver' to ALLOWED_HOSTS.
    

    @boatcoder 评论中的这个解决方法显示了如何将默认服务器名称覆盖为“localhost”:

    request_factory = RequestFactory(**{"SERVER_NAME": "localhost", "wsgi.url_scheme":"https"}).
    

    【讨论】:

    • RequestFactory 有一些缺点,即它将您的服务器命名为testserver,这可能会导致ALLOWED_HOSTS 出现问题,但您可以通过像这样初始化它rf = RequestFactory(**{"SERVER_NAME": "localhost", "wsgi.url_scheme":"https"}) 来解决这个问题。
    • 我尝试使用 RequestFactory 创建一个发布请求(关于登录页面),我该如何解决这个错误:Forbidden (CSRF cookie not set.)
    • 试试这个my_request._dont_enforce_csrf_checks = True,让我们知道它是否有效。如果是,我将编辑我的回复。
    【解决方案2】:

    我如何模拟来自 python 命令行的请求是:

    模拟请求的一种简单方法是:

    >>> from django.urls import reverse
    >>> import requests
    >>> r = requests.get(reverse('app.views.your_view'))
    >>> r.text
    (prints output)
    >>> r.status_code
    200
    

    更新:一定要启动 django shell(通过manage.py shell),而不是经典的 python shell。

    更新2:对于Django

    from django.core.urlresolvers import reverse 
    

    【讨论】:

    • 我在尝试你的方法时得到了这个:requests.exceptions.MissingSchema: Invalid URL '/': No schema supplied. Perhaps you meant http:///?
    • 您可能想在前面加上 "http://localhost:8000" 以便它读取 requests.get("http://192.168.0.1:8000" + reverse(...))
    • 我收到了这个错误[Errno 111] Connection refused 虽然我可以连接我的浏览器。
    • 这与通过命令行使用wgetcurl 请求没有什么不同。
    • 对于 django 1.10+ 使用 django.urls。见这里:docs.djangoproject.com/en/1.10/ref/urlresolvers
    【解决方案3】:

    (参见 tldr;向下)

    这是一个老问题, 但只是添加一个答案,以防有人可能感兴趣。

    虽然这可能不是最好的(或者说 Django)做事的方式。 但你可以尝试这样做。

    在你的 django shell 中

    >>> import requests
    >>> r = requests.get('your_full_url_here')
    

    解释: 我省略了reverse(), 解释是,因为reverse()或多或少, 查找与 views.py 函数关联的 url, 如果您愿意,您可以省略reverse(),并输入整个网址。

    例如,如果您的 django 项目中有一个朋友应用程序, 并且您想在朋友应用程序中查看list_all()(在views.py 中)功能, 那么你可以这样做。

    TLDR;

    >>> import requests
    >>> url = 'http://localhost:8000/friends/list_all'
    >>> r = requests.get(url)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 2016-11-19
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多