There is a way to add features to an existing django command?

后端 未结 3 509
余生分开走
余生分开走 2020-12-14 20:20

I want to run a command just before the a django command is started.

For example:

$ python manage.py runserver
Validating models...

0 errors found
D         


        
3条回答
  •  心在旅途
    2020-12-14 20:52

    To further expand on @Mario César's excellent answer, I would like to provide a modern version of his initial 2011 code adapted for Django 1.8+:

    Before Django 1.8, management commands were based on the optparse module [...] Now that management commands use argparse for argument parsing, all arguments are passed in **options by default [...]

    Source

    Additionally, I would like to point out that the specific command runserver that was chosen in the question has a slight complication making it both a good and bad example.

    Bad example, because the complication is that the command is overridden by Django itself as well. Indeed, Django uses the same method as proposed by Mario: Django overrides it in the staticfiles app (see Django code on github) in order to offer the additional static files options.

    Therefore, it is better to override the staticfiles app command rather than the core command, if one uses static. This answers to @ts_pati's comment too on why there is problem. The Django code of staticfiles is the good example on how to override it, but this time importing the staticfiles in order not to lose that functionality:

    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
    

    EDIT: I would also like to add the order of this in INSTALLED_APPS is apparently important and it has to be before django.contrib.staticfiles.

提交回复
热议问题