63

How can I be certain that my application is running on development server or not? I suppose I could check value of settings.DEBUG and assume if DEBUG is True then it's running on development server, but I'd prefer to know for sure than relying on convention.

Imran
  • 87,203
  • 23
  • 98
  • 131
  • Old ones are good ones! One reason you may need this is that logging.handlers.RotatingFileHandler doesn't work on the development server, so you need to conditionalize LOGGING if you want to use it. – nigel222 Mar 31 '23 at 15:42

15 Answers15

48

I put the following in my settings.py to distinguish between the standard dev server and production:

import sys
RUNNING_DEVSERVER = (len(sys.argv) > 1 and sys.argv[1] == 'runserver')

This also relies on convention, however.

(Amended per Daniel Magnusson's comment)

Aryeh Leib Taurog
  • 5,370
  • 1
  • 42
  • 49
  • 7
    i had to add if len(sys.argv) >1: on prod server to get it working. – Daniel Magnusson Oct 03 '12 at 09:39
  • This is the better answer since it doesn't require a request. I want to do this to conditionally wire up the media urls – Aaron McMillin May 19 '17 at 19:53
  • 1
    Could you explain what is this for? Maybe I do not understand the problem, but this variable stores whether the site is called with manage.py runserver, right? And what do you do with this? I stumble upon this post and this seems new stuff I want to learn. I was looking for a way to detect whether I am on localhost, in that case turn DEBUG on (I am not looking for an answer about this on this post) – aless80 Mar 07 '18 at 02:51
  • @aless80 there are uwsgi-specific stuff you might want to disable when running with the dev-server, like the spooler – BjornW Sep 26 '19 at 13:59
  • 1
    simplified here: https://stackoverflow.com/a/37880897/ – djvg Nov 26 '20 at 10:46
  • What about running migrations (or any other command) on dev server? In my case it tries to connect to the database with the prod server credentials. – martintrapp Sep 16 '21 at 17:07
22
server = request.META.get('wsgi.file_wrapper', None)
if server is not None and server.__module__ == 'django.core.servers.basehttp':
    print('inside dev')

Of course, wsgi.file_wrapper might be set on META, and have a class from a module named django.core.servers.basehttp by extreme coincidence on another server environment, but I hope this will have you covered.

By the way, I discovered this by making a syntatically invalid template while running on the development server, and searched for interesting stuff on the Traceback and the Request information sections, so I'm just editing my answer to corroborate with Nate's ideas.

FlipperPA
  • 13,607
  • 4
  • 39
  • 71
inerte
  • 1,134
  • 1
  • 8
  • 20
  • 4
    +1 for actually trying to address the question i.e. detecting what server is serving up the Django app, rather than relying on settings. For example, there is nothing stopping someone from running in DEBUG mode behind something other than the development web server. – Ryan Duffield Aug 20 '09 at 17:58
  • Another META field that is specific for dev server: SERVER_SOFTWARE has strings `WSGIServer` and `Python` on dev and anything you configure in your HTTP server on "deployed". – zgoda Aug 21 '09 at 08:19
  • I would add a `getattr(server, '__module__', None)` in the second line instead of going directly to the dot notation. You never know... – Tal Weiss Oct 31 '10 at 06:10
  • 1
    Very cool, but I would like to do this once upon startup, and not upon every request. Is that possible? – Tal Weiss Oct 31 '10 at 06:17
  • 1
    @TalWeiss you can add logic to `manage.py` and `wsgi.py` (or keeping with DRY, add the logic to a third file like `setvars.py` that gets imported & called by both). So use logic like the answer above, or another one of these answers, in order to call different variations of `os.environ.setdefault('DJANGO_SETTINGS_MODULE','some.settings.module')`. This assumes you separate your settings module into submodules by environment. On second thought the answer above won't work there since request isn't set yet. But you get the idea. – floer32 Oct 31 '12 at 14:17
  • 1
    In Django 1.5.5 running on OS X, the module name is `wsgiref.util`. So this snippet won't work. – Rockallite Dec 17 '13 at 01:51
  • 1
    in Django 1.8.12 on linux, the module name is also `wsgiref.util` – ckot May 04 '16 at 19:48
19

Usually this works:

import sys

if 'runserver' in sys.argv:
    # you use runserver
Sven R. Kunze
  • 1,909
  • 2
  • 13
  • 17
  • 1
    What would be the case under production environment? Doesn't this mean that `./manage.py runserver` is run and not for example `./manage.py shell_plus` – shwz Sep 29 '21 at 08:35
  • 2
    According to documentation, you should not use 'runserver' in a production setting. Just make sure DEBUG is used correctly; e.g. add safety nets and checks. – Sven R. Kunze Oct 20 '21 at 05:55
17

Typically I set a variable called environment and set it to "DEVELOPMENT", "STAGING" or "PRODUCTION". Within the settings file I can then add basic logic to change which settings are being used, based on environment.

EDIT: Additionally, you can simply use this logic to include different settings.py files that override the base settings. For example:

if environment == "DEBUG":
    from debugsettings import *
Soviut
  • 88,194
  • 49
  • 192
  • 260
7

Relying on settings.DEBUG is the most elegant way AFAICS as it is also used in Django code base on occasion.

I suppose what you really want is a way to set that flag automatically without needing you update it manually everytime you upload the project to production servers.

For that I check the path of settings.py (in settings.py) to determine what server the project is running on:

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

Mind you, you might also prefer doing this check with environment variables as @Soviut suggests. But as someone developing on Windows and serving on Linux checking the file paths was plain easier than going with environment variables.

utku_karatas
  • 6,163
  • 4
  • 40
  • 52
  • 1
    well, apart from occasions when i might adopt same path convention in development and production (which would defeat this), this seems to be the best for me. and +1 for `WhereTheHellIsThisServedException` :-) – JWL Apr 01 '12 at 09:02
4

If you want to switch your settings files automatically dependent on the runtime environment you could just use something that differs in environ, e.g.

from os import environ
if environ.get('_', ''): 
    print "This is dev - not Apache mod_wsgi"         
none
  • 11,793
  • 9
  • 51
  • 87
Ed C
  • 61
  • 2
4

You can determine whether you're running under WSGI (mod_wsgi, gunicorn, waitress, etc.) vs. manage.py (runserver, test, migrate, etc.) or anything else:

import sys
WSGI = 'django.core.wsgi' in sys.modules
OrangeDog
  • 36,653
  • 12
  • 122
  • 207
4

I came across this problem just now, and ended up writing a solution similar to Aryeh Leib Taurog's. My main difference is that I want to differentiate between a production and dev environments when running the server, but also when running some one-off scripts for my app (which I run like DJANGO_SETTINGS_MODULE=settings python [the script] ). In this case, simply looking at whether argv[1] == runserver isn't enough. So what I came up with is to pass an extra command-line argument when I run the devserver, and also when I run my scripts, and just look for that argument in settings.py. So the code looks like this:

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

then, running the django server becomes

python manage.py runserver [whatever options you want] --in-development

and running my scripts is as easy as

DJANGO_SETTINGS_MODULE=settings python [myscript] --in-development

Just make sure the extra argument you pass along doens't conflict with anything django (in reality I use my app's name as part of the argument). I think this is pretty decent, as it lets me control exactly when my server and scripts will behave as prod or dev, and I'm not relying on anyone else's conventions, other than my own.

EDIT: manage.py complains if you pass unrecognized options, so you need to change the code in settings.py to be something like

if sys.argv[0] == 'manage.py' or '--in-development' in sys.argv:
    # ...
    pass

Although this works, I recognize it's not the most elegant of solutions...

Luiz Scheidegger
  • 788
  • 5
  • 12
2

I use:

DEV_SERVERS = [
    'mymachine.local',
]

DEVELOPMENT = platform.node() in DEV_SERVERS

which requires paying attention to what is returned by .node() on your machines. It's important that the default be non-development so that you don't accidentally expose sensitive development information.

You could also look into more complicated ways of uniquely identifying computers.

Carl G
  • 17,394
  • 14
  • 91
  • 115
2

settings.DEBUG could be True and running under Apache or some other non-development server. It will still run. As far as I can tell, there is nothing in the run-time environment short of examining the pid and comparing to pids in the OS that will give you this information.

hughdbrown
  • 47,733
  • 20
  • 85
  • 108
1

Inspired by Aryeh's answer, the trick I devised for my own use is to just look for the name of my management script in sys.argv[0]:

USING_DEV_SERVER = "pulpdist/manage_site.py" in sys.argv[0]

(My use case is to automatically enable Django native authentication when running the test server - when running under Apache, even on development servers, all authentication for my current project is handled via Kerberos)

ncoghlan
  • 40,168
  • 10
  • 71
  • 80
1

One difference between the development and deployment environment is going to be the server that it’s running on. What exactly is different will depend on your dev and deployment environments.

Knowing your own dev and deploy environments, the HTTP request variables could be used to distinguish between the two. Look at request variables like request.META.HTTP_HOST, request.META.SERVER_NAME and request.META.SERVER_PORT and compare them in the two environments.

I bet you’ll find something quite obvious that’s different and can be used to detect your development environment. Do the test in settings.py and set a variable that you can use elsewhere.

Nate
  • 18,752
  • 8
  • 48
  • 54
1

You could check request.META["SERVER_SOFTWARE"] value:

dev_servers = ["WSGIServer", "Werkzeug"]
if any(server in request.META["SERVER_SOFTWARE"] for server in dev_servers):
    print("is local")
mislavcimpersak
  • 2,880
  • 1
  • 27
  • 30
1

Simple you may check the path you work on server. Something like:

import os
SERVER = True if os.path.exists('/var/www/your_project') else False
Cappittall
  • 3,300
  • 3
  • 15
  • 23
0

One approach is to create an environment variable on your dev machine such as RUNNING_IN_DEVELOPMENT = 1. JetBrains, for example, lets you do this in the Configuration Dialog.

Then in settings.py you can do:

try:
    running_in_development = os.getenv('RUNNING_IN_DEVELOPMENT')
    DEBUG = True if running_in_development else False
except Exception as e:
    DEBUG = False
VikR
  • 4,818
  • 8
  • 51
  • 96