Where to put Django startup code?

99封情书 提交于 2019-11-26 05:22:19

问题


I\'d like to have these lines of code executed on server startup (both development and production):

from django.core import management
management.call_command(\'syncdb\', interactive=False)

Putting it in settings.py doesn\'t work, as it requires the settings to be loaded already.

Putting them in a view and accessing that view externally doesn\'t work either, as there are some middlewares that use the database and those will fail and not let me access the view.

Putting them in a middleware would work, but that would get called each time my app is accessed. An possible solution might be to create a middleware that does all the job and then removes itself from MIDDLEWARE_CLASSES so it\'s not called anymore. Can I do that without too much monkey-patching?


回答1:


Write middleware that does this in __init__ and afterwards raise django.core.exceptions.MiddlewareNotUsed from the __init__, django will remove it for all requests :). __init__ is called at startup by the way, not at the first request, so it won't block your first user.

There is talk about adding a startup signal, but that won't be available soon (a major problem for example is when this signal should be sent)

Related Ticket: https://code.djangoproject.com/ticket/13024

Update: Django 1.7 includes support for this. (Documentation, as linked by the ticket)




回答2:


If you were using Apache/mod_wsgi for both, use the WSGI script file described in:

http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

Add what you need after language translations are activated.

Thus:

import sys

sys.path.insert(0, '/usr/local/django/mysite')

import settings

import django.core.management
django.core.management.setup_environ(settings)
utility = django.core.management.ManagementUtility()
command = utility.fetch_command('runserver')

command.validate()

import django.conf
import django.utils

django.utils.translation.activate(django.conf.settings.LANGUAGE_CODE)

# Your line here.
django.core.management.call_command('syncdb', interactive=False)

import django.core.handlers.wsgi

application = django.core.handlers.wsgi.WSGIHandler()



回答3:


You can create a custom command and write your code in the handle function. details here https://docs.djangoproject.com/en/dev/howto/custom-management-commands/

Then you can create a startup script that runs the django server then executes your new custom command.




回答4:


If you are using mod_wsgi you can put it in the wsgi start app




回答5:


Here is how I work around the missing startup signal for Django: https://github.com/lsaffre/djangosite/blob/master/djangosite/models.py The code that is being called there is specific to my djangosite project, but the trick to get it called by writing a special app (based on an idea by Ross McFarland) should work for other environments. Luc




回答6:


In Django 1.7+ if you want to run a startup code and,

1. Avoid running it in migrate, makemigrations, shell sessions, ...

2. Avoid running it twice or more

A solution would be:

file: myapp/apps.py

from django.apps import AppConfig

def startup():
    # startup code goes here

class MyAppConfig(AppConfig):
    name = 'myapp'
    verbose_name = "My Application"
    def ready(self):
        import os
        if os.environ.get('RUN_MAIN'):
            startup()

file: myapp/__init__.py

default_app_config = 'myapp.apps.MyAppConfig'

This post is using suggestions from @Pykler and @bdoering



来源:https://stackoverflow.com/questions/2781383/where-to-put-django-startup-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!