我想在启动django命令之前运行命令。
例如:
$ python manage.py runserver
Validating models...
0 errors found
Django version 1.3, using settings 'creat1va.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
(started some command in the background)
[10/Jul/2011 21:50:26] "GET / HTTP/1.1" 200 1611
[10/Jul/2011 21:50:26] "GET /assets/css/master.css HTTP/1.1" 404 1783
[10/Jul/2011 21:50:26] "GET /assets/images/misc/logo.png HTTP/1.1" 404 1801
[10/Jul/2011 21:50:26] "GET /assets/images/icons/bo.gif HTTP/1.1" 404 1798
[10/Jul/2011 21:50:28] (My background process) "Some nice Feedback"
主要思想是启动后台进程,并输出日志记录。
有没有办法实现这一目标,而不会破坏django来源?
答案 0 :(得分:17)
只要意识到您可以轻松地覆盖这些命令,就像使用同名命令创建应用程序一样。
所以我创建一个应用程序并创建一个与runserver同名的文件,稍后再扩展runserver基类以在运行之前添加新功能。
例如,我想在runserver启动之前运行命令$ compass watch,并使其在runserver执行时继续运行。
"""
Start $compass watch, command when you do $python manage.py runserver
file: main/management/commands/runserver.py
Add ´main´ app to the last of the installed apps
"""
from optparse import make_option
import os
import subprocess
from django.core.management.base import BaseCommand, CommandError
from django.core.management.commands.runserver import BaseRunserverCommand
from django.conf import settings
class Command(BaseRunserverCommand):
option_list = BaseRunserverCommand.option_list + (
make_option('--adminmedia', dest='admin_media_path', default='',
help='Specifies the directory from which to serve admin media.'),
make_option('--watch', dest='compass_project_path', default=settings.MEDIA_ROOT,
help='Specifies the project directory for compass.'),
)
def inner_run(self, *args, **options):
self.compass_project_path = options.get('compass_project_path', settings.MEDIA_ROOT)
self.stdout.write("Starting the compass watch command for %r\n" % self.compass_project_path)
self.compass_pid = subprocess.Popen(["compass watch %s" % self.compass_project_path],
shell=True,
stdin=subprocess.PIPE,
stdout=self.stdout,
stderr=self.stderr)
self.stdout.write("Compas watch process on %r\n" % self.compass_pid.pid)
super(Command, self).inner_run(*args, **options)
这很好用。
有关django命令的详细信息,请查看https://docs.djangoproject.com/en/dev/howto/custom-management-commands/
希望有人找到这个有用的
答案 1 :(得分:5)
为了进一步扩展@MarioCésar的优秀答案,我想提供适用于Django 1.8 +的2011年初代码的现代版本:
在Django 1.8之前,管理命令基于optparse模块[...]现在管理命令使用argparse进行参数解析,默认情况下所有参数都在**选项中传递[...]
此外,我想指出在问题中选择的特定命令runserver
有轻微的复杂性,使其成为一个好的和坏的例子。
错误的例子,因为复杂的是Django本身也重写了命令。实际上,Django使用的方法与Mario提出的方法相同:Django在staticfiles应用程序中覆盖它(参见Django code on github),以便提供额外的静态文件选项。
因此,如果使用static,最好覆盖staticfiles app命令而不是core命令。这也回答了@ ts_pati关于为何存在问题的评论。静态文件的Django代码是如何覆盖它的好例子,但是这次导入静态文件以便不丢失该功能:
from django.contrib.staticfiles.management.commands.runserver import Command as StaticfilesRunserverCommand
class Command(StaticfilesRunserverCommand):
help = "Starts a lightweight Web server for development, serves static files and does some custom fancy stuff."
def add_arguments(self, parser):
super(Command, self).add_arguments(parser)
parser.add_argument('--my-custom-argument', action="...", dest='my_custom_handler', default=True, help='do some stuff in fancy ways')
def get_handler(self, *args, **options):
"""
My fancy stuff function.
"""
handler = super(Command, self).get_handler(*args, **options)
my_custom_handler = options.get('my_custom_handler', True)
# do stuff here
return handler
编辑:我还想在INSTALLED_APPS
中添加此顺序显然非常重要,必须在django.contrib.staticfiles
之前。
答案 2 :(得分:1)
在运行命令的应用程序中编写自己的管理命令,然后调用Django的内置实现。