3

I have a Django management command, which I pass like this:

python manage.py tenant_command generate_weekly_invoice --start_date 2020-11-30 00:00:00 --end_date 2020-12-06 23:59:00 --schema=schema_name

This doesn't work and I get an error saying that:

argument 1 must be str, not None

I suspect this is to do with the way the actual string of the date 2020-11-30 00:00:00 is being formatted. My management command code is below

generate_weekly_invoice.py

class Command(BaseCommand):
    help = 'Generates weekly invoice'

    def add_arguments(self, parser):
        parser.add_argument('--start_date', nargs='+')
        parser.add_argument('--end_date', nargs='+')
    
    def handle(self, *args, **options):

        start_str = options.get('--start_date')
        end_str = options.get('--end_date')

        start_date = datetime.datetime.strptime(start_str, '%Y-%m-%d %H:%M:%S')
        end_date = datetime.datetime.strptime(end_str, '%Y-%m-%d %H:%M:%S')

        ___Logic goes here___

Any help is appreciated

*** Edit:

I should have explained, that I have passed the string in quotation marks but it still returns the same error.

Rutnet
  • 1,533
  • 5
  • 26
  • 48

1 Answers1

4

This is because a space is seen as a parameter separator. You can wrap the parameters over single/double quotes, so --start_date '2020-11-30 00:00:00' instead of --start_date 2020-12-06 23:59:00:

python manage.py tenant_command generate_weekly_invoice --start_date '2020-11-30 00:00:00' --end_date '2020-12-06 23:59:00' --schema=schema_name
#                                      pass the datetimes as a single parameter ↑                                ↑

This is because a space is seen as a parameter separator. You can wrap the parameters over single/double quotes, so --start_date '2020-11-30 00:00:00' instead of --start_date 2020-12-06 23:59:00:

python manage.py tenant_command generate_weekly_invoice --start_date '2020-11-30 00:00:00' --end_date '2020-12-06 23:59:00' --schema=schema_name
#                                      pass the datetimes as a single parameter ↑                                ↑

additionally, your misunderstood how parameters are handled. This is without the double hyphens. You can thus use options.get('start_date'), but it is better to simply use the names of the parameters, and drop the nargs='+', since that means one can pass multiple --start_dates, etc:

class Command(BaseCommand):
    help = 'Generates weekly invoice'

    def add_arguments(self, parser):
        parser.add_argument('--start_date')  # ← no nargs='+'
        parser.add_argument('--end_date')    # ← no nargs='+'
    
    def handle(self, start_date, end_date, **kwargs):
        start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d %H:%M:%S')
        end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d %H:%M:%S')

If you want to parse --start_date multiple times, then you can use nargs='+', but then start_date and end_date will be lists of strings, not a single string, so then you need to perform a mapping.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • This doesn't work, I tried this previously – Rutnet Dec 04 '20 at 11:49
  • Thank you, I am a little bit closer but now get this error: "handle() got an unexpected keyword argument 'verbosity' – Rutnet Dec 04 '20 at 12:04
  • @Rutnet: sorry, made a typo, at the end, `verbosity` and `traceback` should be added. – Willem Van Onsem Dec 04 '20 at 12:09
  • Now I get this error, handle() got an unexpected keyword argument 'settings'. Looking at this https://stackoverflow.com/questions/41401202/django-command-throws-typeerror-handle-got-an-unexpected-keyword-argument it says too many arguments passed – Rutnet Dec 04 '20 at 12:20