如何判断我的Django应用程序是否在开发服务器上运行?

65

如何确保我的应用程序是否在开发服务器上运行?我可以检查settings.DEBUG的值并假设如果DEBUGTrue,那么它正在运行开发服务器,但我更愿意确定而不是依赖惯例。


老的东西也是好的!你需要这个的一个原因是 logging.handlers.RotatingFileHandler 在开发服务器上不起作用,所以如果你想使用它,你需要有条件地设置 LOGGING。 - nigel222
16个回答

48
我将以下代码放入settings.py中以区分标准开发服务器和生产服务器:
import sys
RUNNING_DEVSERVER = (len(sys.argv) > 1 and sys.argv[1] == 'runserver')

这也依赖于惯例。

(根据Daniel Magnusson的评论进行了修正)


7
在生产服务器上,我不得不添加 "if len(sys.argv)>1:" 才能使它正常工作。 - Daniel Magnusson
这是更好的答案,因为它不需要请求。我想通过条件方式连接媒体URL。 - Aaron McMillin
1
你能解释一下这是干什么用的吗?也许我没有理解问题,但这个变量存储的是网站是否使用manage.py runserver调用的,对吧?那么你要用它来做什么呢?我偶然看到了这篇文章,这似乎是我想学习的新东西。我正在寻找一种方法来检测我是否在本地主机上,在这种情况下打开DEBUG(我不是在这篇文章中寻找答案)。 - aless80
1
https://dev59.com/DHM_5IYBdhLWcg3wp00X#37880897/ - djvg
这对我有所帮助。 - Rezaul Karim Shaon
显示剩余2条评论

22
server = request.META.get('wsgi.file_wrapper', None)
if server is not None and server.__module__ == 'django.core.servers.basehttp':
    print('inside dev')
当然,wsgi.file_wrapper 可能已经在META中设置,并且在另一个服务器环境中,它的类来自名为django.core.servers.basehttp 的模块,但我希望这可以解决您的问题。顺便说一下,我是通过在开发服务器上运行语法无效的模板,并搜索TracebackRequest information部分的有趣内容来发现这个问题的,所以我只是编辑我的答案来支持Nate的想法。

4
感谢您的信任。我的任务是将您提供的内容翻译成中文,并尽可能保持原意和简洁,不包含任何解释或额外的信息。对于实际尝试解决问题的+1,即检测哪个服务器正在提供Django应用程序,而不是依赖于设置。例如,没有什么可以阻止某人在开发Web服务器之外的其他位置运行DEBUG模式。 - Ryan Duffield
1
非常酷,但我想在启动时只执行一次,而不是每次请求都执行。这可能吗? - Tal Weiss
1
@TalWeiss 你可以在 manage.pywsgi.py 中添加逻辑(或者按照DRY的原则,将逻辑添加到第三个文件中,比如 setvars.py ,然后由两个文件导入并调用)。因此,使用像上面答案中所示的逻辑或其他这些答案中的逻辑,以便调用不同版本的 os.environ.setdefault('DJANGO_SETTINGS_MODULE','some.settings.module') 。这假定您通过环境将设置模块分成子模块。 经过再次思考,上面的回答不会奏效,因为请求(request)尚未设置。但是你明白我的意思。 - floer32
1
在运行于 OS X 上的 Django 1.5.5 中,模块名称为 wsgiref.util。因此,这段代码片段无法工作。 - Rockallite
1
在Linux上的Django 1.8.12中,该模块的名称也是wsgiref.util - ckot
显示剩余2条评论

19

通常情况下,这个是有效的:

import sys

if 'runserver' in sys.argv:
    # you use runserver

1
在生产环境下会是什么情况?这难道不意味着运行的是 ./manage.py runserver 而不是例如 ./manage.py shell_plus 吗? - shwz
2
根据文档,您不应在生产环境中使用“runserver”。只需确保正确使用DEBUG;例如添加安全网和检查。 - Sven R. Kunze

17

通常我会设置一个名为environment的变量,并将其设置为"DEVELOPMENT"、"STAGING"或"PRODUCTION"。然后在设置文件中,我可以添加基本的逻辑来根据环境改变正在使用的设置。

编辑:此外,您还可以使用此逻辑包含不同的settings.py文件来覆盖基础设置。例如:

if environment == "DEBUG":
    from debugsettings import *

7

我认为最优雅的方式是依赖于settings.DEBUG,因为在Django代码库中也有时会使用它。

我猜你真正想要的是一种自动设置该标志的方法,而不需要每次将项目上传到生产服务器时手动更新它。

为了实现这一点,在settings.py中,我会检查settings.py的路径来确定项目运行在哪个服务器上:

if __file__ == "path to settings.py in my development machine":
    DEBUG = True
elif __file__ in [paths of production servers]:
    DEBUG = False
else:
    raise WhereTheHellIsThisServedException()

请注意,你可能更喜欢像@Soviut建议的那样使用环境变量进行此检查。但是作为一个在Windows上开发并在Linux上提供服务的人,检查文件路径比使用环境变量更容易。


1
除非在开发和生产中采用相同的路径约定(这将使此方法无效),否则这似乎对我来说是最好的选择。并且为WhereTheHellIsThisServedException加一分 :-) - JWL

4

您可以确定当前是在运行WSGI(如mod_wsgi、gunicorn、waitress等)还是manage.py(如runserver、test、migrate等)或其他内容:

import sys
WSGI = 'django.core.wsgi' in sys.modules

4

我刚刚遇到了这个问题,最终写出了与Aryeh Leib Taurog类似的解决方案。我的主要区别在于,当运行服务器时,我希望区分生产环境和开发环境,但是当运行一些应用程序的单次脚本时(我像这样运行:DJANGO_SETTINGS_MODULE=settings python [the script]),也需要区分环境。在这种情况下,仅查看argv[1] == runserver是否足够。所以我想到的办法是,在运行devserver时传递一个额外的命令行参数,并且在运行我的脚本时也是如此,并在settings.py中查找该参数。因此,代码如下:

if '--in-development' in sys.argv:
    ## YES! we're in dev
    pass
else:
    ## Nope, this is prod
    pass

然后,运行Django服务器变为: python manage.py runserver [任何选项] --in-development
而运行我的脚本就像这样简单:
DJANGO_SETTINGS_MODULE=settings python [myscript] --in-development
只需确保您传递的额外参数不会与任何Django冲突(实际上,我使用我的应用程序名称作为参数的一部分)。我认为这很不错,因为它让我完全控制我的服务器和脚本何时以prod或dev模式运行,并且我不依赖于任何其他人的约定,除了我自己的。
编辑:如果您传递未识别的选项,manage.py会发出警告,因此您需要更改settings.py中的代码,使其类似于:
if sys.argv[0] == 'manage.py' or '--in-development' in sys.argv:
    # ...
    pass

尽管这样可以运行,但我认识到这不是最优雅的解决方案...

4
如果您想根据运行时环境自动切换设置文件,您可以使用在环境中不同的东西,例如。
from os import environ
if environ.get('_', ''): 
    print "This is dev - not Apache mod_wsgi"         

2

我使用:

DEV_SERVERS = [
    'mymachine.local',
]

DEVELOPMENT = platform.node() in DEV_SERVERS

这需要注意在您的机器上通过.node()返回的内容。默认设置为非开发模式非常重要,以避免意外暴露敏感的开发信息。

您还可以查看更复杂的唯一标识计算机的方法


2

设置中的DEBUG可能为True并在Apache或其他非开发服务器下运行。它仍将运行。据我所知,除了检查pid并将其与操作系统中的pids进行比较之外,运行时环境中似乎没有任何信息可以提供这些信息。


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