1

I need to run a Custom Django Management Command (module named populate_db.py) included in a management/commands directory. It populates a database.

restaurant/
    __init__.py
    models.py
    management/
        commands/
            _private.py
            populate_db.py
    tests.py
    views.py
    formDict.py

I want the command to take a mandatory argument as a dictionary. The mentioned dictionary can be obtained from the execution of another program named formDict.py

So I want a one-line command which will run formDict.py and consecutively take its result as an argument for my Custom Django Management Command python manage.py populate_db.

Is it possible to form such a command at all? If not, how to implement the idea alternatively?

aspiring
  • 357
  • 2
  • 3
  • 11
  • You can run django background tasks take a look at my answer here: https://stackoverflow.com/questions/54225303/signal-django-to-run-a-task/54225921#54225921 and if you find it useful then don't forget to upvote it so that the community can take advantage of it. :) – Ahtisham Feb 03 '19 at 22:53

2 Answers2

1

If fromDict.py prints to terminal (STDOUT), you can use a pipe (|) to get the parameter from STDIN in your management command, you can use sys.stdin for that. As you may want to execute the command by itself, it is a good idea to accept a string by parameter too.

Your management command would look line:

# populate_db.py
import argparse
import ast
import sys

from django.core.management.base import BaseCommand, CommandError


class Command(BaseCommand):
    help = 'Polulate the Database'

    def add_arguments(self, parser):
        parser.add_argument(
            'input_dict',
            nargs='?',
            type=str,
            default=None
        )

    def handle(self, *args, **options):
        if options['input_dict']:
            input_dict = options['input_dict']
        else:
            input_dict = sys.stdin.read()

        try:
            data = ast.literal_eval(input_dict)
        except SyntaxError:
            raise CommandError(f'Invalid dict input: {input_dict}')

        # populate the DB with data

You can execute that command with either:

Getting the dict from STDIN

python fromDict.py | python yourproject/manage.py populate_db

or

Passing the dict by parameter

python yourproject/manage.py populate_db '{'some': 'dict'}'

Note: Take care with literal_eval if the dict comes from an untrusted source, as someone could exploit it (with very large values, for exemple) to break the python interpreter.

Renan Ivo
  • 1,368
  • 9
  • 17
  • I've done the code with python 3.7. If you are using python < 3.6, you need to replace the [f-string](https://www.python.org/dev/peps/pep-0498/) with `.format`. – Renan Ivo Feb 04 '19 at 02:02
  • @aspiring The error you posted suggests your attribute is required. Did you added `nargs='?',` to `parser.add_argument` as the code in my answer does? Are you handling the absence of the parameter and getting it from stdin? If you can post the current code of `populate_db.py`, it might help. – Renan Ivo Feb 04 '19 at 17:28
0

Wrap the logic of formDict in a function. Call it inside the handle function of populate_db.py to access the result returned from form_dict.

or

move formDict.py to management/commands/ and use call_command inside formDict to call populate_db. https://docs.djangoproject.com/en/2.1/ref/django-admin/#running-management-commands-from-your-code.

Gowtham_k
  • 1
  • 1
  • 3