如何在 Django 中进行故障排除?

Posted

技术标签:

【中文标题】如何在 Django 中进行故障排除?【英文标题】:How do I troubleshoot in Django? 【发布时间】:2014-12-14 23:19:27 【问题描述】:

我来自 php 背景,我一直在尝试学习 Python,但在调试时遇到了很多麻烦,因为我还不确定如何在 Django 或 Python 中进行此操作.

我习惯于在 PHP 中使用 print_rvar_dump 一切。我可以在控制器中、在服务层中执行此操作,甚至模型和数据都会显示在我的网络浏览器中。

我不能在 Django 中做到这一点。根据我在做什么,尝试从我的视图中对一个对象执行print 会导致页面关闭或向我的控制台输出一些对我没有帮助的内容。这是一个例子:

class Page(View):
    def get(self, request, *args, **kwargs):
       response = Data.objects.all()

       # for whatever reason, I want to print something right now:
       print response

       # return JsonResponse('success':response)

以上内容将完全删除我的页面,并带有一条通知:

The view didn't return an HttpResponse object. It returned None instead.

在使用 CBV 的某些情况下,我注意到我可以将数据转储到控制台等某个地方。但这对我没有任何帮助。例如,如果我试图从上面查看 response 的内容,它会显示如下:

[object Object] [object Object] [object Object]

var_dump 可以让我真正看到它的内部。

所以我猜我做错了。人们在 Python 中调试时是否只是转储数据?如果他们这样做,您如何执行此操作,它是否显示在 Web 浏览器或控制台中?如果没有,我该如何处理 Django 中的基本故障排除?示例场景:

    我想查看列表或字典的内容 我想查看 ORM 执行的原始 sql 查询 我想通过在前端输出一些文本来查看函数是否正在执行

【问题讨论】:

【参考方案1】:

基本问题是你习惯了 PHP 是如何连接到整个请求/响应链中的,而这不是 Python 在开发 Web 应用程序时的配置方式。

在 PHP 世界中,服务器保证响应,从而关闭请求/响应周期。 PHP 文件是浏览器直接请求的,所以你不知道后台实际发生了什么。

典型的 PHP 请求与对任何其他静态资产的请求相同,例如普通的 index.html 文件或 logo.gif。浏览器请求,Web服务器接受请求,然后返回响应;唯一的区别是,如果请求带有.php 的文件,那么它会经过一个中间步骤,PHP 解释器评估该文件,并将结果发送回客户端。

然而,在 Python 中,当发出映射到 Python 后端进程(有时称为上游进程)的请求时;网络服务器等待进程的响应(可以调整超时)。如果在定义的超时时间内没有收到响应,网络服务器会发送一个超时错误页面 (504 ERROR)。

Python 进程有责任按照浏览器的预期发送正确的响应(包括所有标头等)。在 PHP 中,这对您(作为开发人员)是隐藏的,因为 PHP 引擎会为您添加这些额外信息。因此,当您的 Python 代码不发送此类响应时(如您的情况),django 会通过打印友好的错误消息来帮助您。

在您的情况下 - 视图没有返回响应;它只是打印一些东西。此打印语句将转到应用程序的标准输出(或错误流)(如果您在 shell 上启动它,将在控制台上打印,或者写入服务器的日志等)它不会被发送回客户端(浏览器)。

为了调试 django 应用程序:

    确保在您的settings.py 中设置了DEBUG = True 使用python manage.py runserver 运行您的应用程序

现在,当您执行任何打印语句时,它将显示在控制台上,并且如果您的应用程序代码中有错误 - 只要您返回有效响应 - 您将获得一个丰富的错误页面以及堆栈跟踪以帮助识别问题。

在开发过程中不再有“在浏览器上调试语句和打印东西”;这就是 Python 连接到网络世界的方式。

关于您的其他问题:

    我想查看列表或字典的内容

    只需打印即可。输出将在您的控制台上(与您编写 python manage.py runserver 的地方相同)

    我想查看 ORM 执行的原始 sql 查询

    如果您在 django shell 中进行测试,您只需将 .query 放在 ORM 调用的末尾即可查看正在发送的查询:

     >>> result = MyModel.objects.filter(foo='bar')
     >>> result.query
     (query printed here)
    

    如需更丰富的调试体验,请安装django_debug_toolbar

    我想通过在前端输出一些文本来查看是否正在执行函数

    没有“输出到前端”。对于这样的事情,你可以print()你需要的,或者更好的use the logging system。

【讨论】:

【参考方案2】:

首先,您收到错误的原因不是因为您正在打印,而是因为您注释掉了返回:

class Page(View):
    def get(self, request, *args, **kwargs):
       response = Data.objects.all()

       # for whatever reason, I want to print something right now:
       print response

       return JsonResponse('success':response) # <-- dont comment this out

其次,打印任意对象并不总是能提供最好的信息量。如果某些东西定义了 __str____unicode__ 方法,那么这就是将打印到控制台的内容。否则,将打印对象名称及其内存 ID。不是最有用的。打印对象不会进行“深度”打印。

你可以尝试打印出局部和全局:

print(locals())
print(globals())

或者将一个对象序列化为 JSON 并打印出来:

print(json.dumps(response)) # some objects may not be serialisable to JSON though.

但您也可能无法从中获得所需的详细信息。另一种方法是在调试模式下运行您的网络服务器,并引发异常:

# settings.py
DEBUG = True

# views.py
def my_view(request):
    raise Exception('debug')

.. 并依靠 django 向您显示调试错误页面,其中包括堆栈跟踪,并允许您检查每个帧中可用的所有变量。

【讨论】:

+1 表示DEBUG 模式——这正是它的用途。【参考方案3】:

首先,Django 视图需要返回某种 HttpResponse 对象。从文档 - 与 Django 自动创建的 HttpRequest 对象相比,HttpResponse 对象是您的责任。您编写的每个视图都负责实例化、填充和返回 HttpResponse。

您可以使用许多类来返回该响应(render_to_response、HttpResponseRedirect、JsonResponse 等等——https://docs.djangoproject.com/en/dev/ref/request-response/#httpresponse-subclasses)。如果您去掉 #.

您可以使用 Python 的 dir 函数来代替 var_dump。将显示类或类实例的所有属性。见-Is there a function in Python to print all the current properties and values of an object?

    您可以打印字典。有很多方法可以做到这一点。

    对于 your_dictionary.items() 中的键、值: 打印(键,“:”,值)

    很容易做到。打印 Data.objects.all().query 。见-How to show the SQL Django is running

    或者您可以在函数内部添加打印语句(或声明函数正在执行的装饰器)。

这些是 Django 和 Python 的基本部分。不要粗鲁,但你的时间可能会更好地花在完整的教程上,而不是着手自己的项目。一旦点击,它将非常简单。 MVC/MVT 框架的结构与 PHP 不同,您需要习惯在其中工作,否则会感到沮丧。

【讨论】:

以上是关于如何在 Django 中进行故障排除?的主要内容,如果未能解决你的问题,请参考以下文章

如何对 Snowpipe 自动摄取故障进行故障排除?

如何对运行 Android 11 (SDK 30) 的应用程序崩溃进行故障排除

如何用路由器日志快速定位及排除故障

由他们自己的开发人员在 Docker 容器中进行故障排除

如何获取 Binder 事务缓冲区的内容以进行故障排除

如何在多写入器情况下对文件支持的共享内存中的大页进行故障排除