Last active
January 16, 2026 09:48
-
-
Save virtualstaticvoid/b43dbb6743594e66702ee530391a7cc4 to your computer and use it in GitHub Desktop.
Django Run Script Management Command
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # | |
| # execute using the Django `runscript` management command | |
| # | |
| # > python manage.py runscript <script.py> | |
| # | |
| import argparse | |
| import logging | |
| from typing import List, TYPE_CHECKING | |
| logger = logging.getLogger(__name__) | |
| if TYPE_CHECKING: | |
| __script_args__: List[str] = [] | |
| def example(): | |
| logger.info("Running example") | |
| logger.info(f"CLI arguments: {__script_args__}") | |
| # TODO: write code to do whatever needs to be done... | |
| return None | |
| # check for entrypoint | |
| if __name__ == "__django_script__": | |
| example() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import argparse | |
| import os | |
| import sys | |
| import traceback | |
| from typing import List | |
| from django.core.management.base import BaseCommand, CommandError | |
| ENTRYPOINT = "__django_script__" | |
| def _validate_file_exists(path): | |
| abs_path = os.path.abspath(path) | |
| if not os.path.isfile(abs_path): | |
| raise argparse.ArgumentTypeError( | |
| f"The file '{path}' does not exist or is not a valid file." | |
| ) | |
| return abs_path | |
| class Command(BaseCommand): | |
| help = "Runs a Python script in the context of the Django application." | |
| def add_arguments(self, parser): | |
| parser.add_argument( | |
| "script", | |
| type=_validate_file_exists, | |
| help="Python script to execute.", | |
| ) | |
| parser.add_argument( | |
| "script_args", | |
| nargs=argparse.REMAINDER, | |
| help="Arguments to pass to the script.", | |
| ) | |
| def handle(self, *args, script: str, script_args: List[str], **options): | |
| try: | |
| with open(script, "r") as f: | |
| code = f.read() | |
| # rudimentary entrypoint check | |
| if ENTRYPOINT not in code: | |
| self.stderr.write( | |
| self.style.ERROR( | |
| f"The '{script}' script doesn't provide the '{ENTRYPOINT}' entrypoint." | |
| ) | |
| ) | |
| sys.exit(1) | |
| # https://docs.python.org/3.12/library/functions.html#compile | |
| compiled = compile(code, script, "exec") | |
| exec_globals = { | |
| "__file__": script, | |
| "__name__": ENTRYPOINT, | |
| "__script_args__": script_args, | |
| } | |
| # https://docs.python.org/3.12/library/functions.html#exec | |
| exec(compiled, exec_globals) | |
| except SyntaxError as e: | |
| raise CommandError( | |
| f"Syntax error in '{script}' at line {e.lineno}: {e.msg}" | |
| ) | |
| except Exception as e: | |
| tb = traceback.format_exc() | |
| raise CommandError(f"Error while executing '{script}': {e}\n{tb}") | |
| self.stdout.write( | |
| self.style.SUCCESS(f"Executed '{script}' script successfully.") | |
| ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment