2015-08-16 23 views
6

Tôi đang cố gắng sử dụng số call_command của Django theo cách rất giống với this question without an answer.đối số call_command là bắt buộc

Con đường tôi đang gọi nó là:

args = [] 
    kwargs = { 
     'solr_url': 'http://127.0.0.1:8983/solr/collection1', 
     'type': 'opinions', 
     'update': True, 
     'everything': True, 
     'do_commit': True, 
     'traceback': True, 
    } 
    call_command('cl_update_index', **kwargs) 

Về lý thuyết, mà nên làm việc, theo the docs. Nhưng nó không hoạt động, nó chỉ không.

Dưới đây là phương pháp add_arguments cho các lớp học chỉ huy của tôi:

def add_arguments(self, parser): 
    parser.add_argument(
     '--type', 
     type=valid_obj_type, 
     required=True, 
     help='Because the Solr indexes are loosely bound to the database, ' 
      'commands require that the correct model is provided in this ' 
      'argument. Current choices are "audio" or "opinions".' 
    ) 
    parser.add_argument(
     '--solr-url', 
     required=True, 
     type=str, 
     help='When swapping cores, it can be valuable to use a temporary ' 
      'Solr URL, overriding the default value that\'s in the ' 
      'settings, e.g., http://127.0.0.1:8983/solr/swap_core' 
    ) 

    actions_group = parser.add_mutually_exclusive_group() 
    actions_group.add_argument(
     '--update', 
     action='store_true', 
     default=False, 
     help='Run the command in update mode. Use this to add or update ' 
      'items.' 
    ) 
    actions_group.add_argument(
     '--delete', 
     action='store_true', 
     default=False, 
     help='Run the command in delete mode. Use this to remove items ' 
      'from the index. Note that this will not delete items from ' 
      'the index that do not continue to exist in the database.' 
    ) 
    parser.add_argument(
     '--optimize', 
     action='store_true', 
     default=False, 
     help='Run the optimize command against the current index after ' 
      'any updates or deletions are completed.' 
    ) 
    parser.add_argument(
     '--do-commit', 
     action='store_true', 
     default=False, 
     help='Performs a simple commit and nothing more.' 
    ) 

    act_upon_group = parser.add_mutually_exclusive_group() 
    act_upon_group.add_argument(
     '--everything', 
     action='store_true', 
     default=False, 
     help='Take action on everything in the database', 
    ) 
    act_upon_group.add_argument(
     '--query', 
     help='Take action on items fulfilling a query. Queries should be ' 
      'formatted as Python dicts such as: "{\'court_id\':\'haw\'}"' 
    ) 
    act_upon_group.add_argument(
     '--items', 
     type=int, 
     nargs='*', 
     help='Take action on a list of items using a single ' 
      'Celery task' 
    ) 
    act_upon_group.add_argument(
     '--datetime', 
     type=valid_date_time, 
     help='Take action on items newer than a date (YYYY-MM-DD) or a ' 
      'date and time (YYYY-MM-DD HH:MM:SS)' 
    ) 

Không có vấn đề gì tôi làm ở đây, tôi nhận được:

CommandError: Error: argument --type is required

Bất kỳ ý tưởng? Nếu bạn thực sự tò mò, bạn có thể see the entire code here.

+0

action = store_true và default = False mâu thuẫn với nhau. 'store_true' là bí danh cho' store_const' với 'const = True' – Incognos

Trả lời

10

Bạn đã xác định đối số có cờ '--type' và đặt nó là required. Dòng lệnh đó sẽ yêu cầu một chuỗi hoặc chuỗi trông giống như --type avalue.

này trông giống như một phần liên quan của call_command:

def call_command(name, *args, **options): 
    .... 
    parser = command.create_parser('', name) 
    if command.use_argparse: 
     # Use the `dest` option name from the parser option 
     opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest 
         for s_opt in parser._actions if s_opt.option_strings} 
     arg_options = {opt_mapping.get(key, key): value for key, value in options.items()} 
     defaults = parser.parse_args(args=args) 
     defaults = dict(defaults._get_kwargs(), **arg_options) 
     # Move positional args out of options to mimic legacy optparse 
     args = defaults.pop('args',()) 

Nó tạo ra một phân tích cú pháp, sử dụng nó là lý lẽ của riêng cộng với những người bạn thêm vào.

parser._actions if s_opt.option_strings là các đối số (Hành động) có cờ tùy chọn (bắt đầu bằng - hoặc -). opt_mapping là bản đồ giữa các chuỗi cờ (trừ đi số -s hàng đầu) và thuộc tính 'dest'.

arg_options chuyển đổi **kwargs thành thứ gì đó có thể được hợp nhất với đầu ra parser.

defaults = parser.parse_args(args=args) thực hiện phân tích cú pháp thực tế. Tức là, đó là mã duy nhất thực sự sử dụng cơ chế phân tích cú pháp argparse. Vì vậy, phần *args trong cuộc gọi của bạn mô phỏng tạo ra sys.argv[1:] từ một cuộc gọi tương tác.

Dựa trên việc đọc mà tôi nghĩ rằng điều này sẽ làm việc:

args = [ 
    '--solr-url', 'http://127.0.0.1:8983/solr/collection1', 
    '--type', 'opinions', 
    '--update' 
    '--everything', 
    '--do_commit', 
    '--traceback', 
} 
call_command('cl_update_index', *args) 

Thay vì **kwargs tôi đi qua trong các giá trị như một danh sách các chuỗi. Hoặc hai đối số yêu cầu có thể được chuyển vào args và các đối số còn lại trong **kwargs.

args = ['--solr-url', 'http://127.0.0.1:8983/solr/collection1', 
    '--type', 'opinions'] 
kwargs = { 
    'update': True, 
    'everything': True, 
    'do_commit': True, 
    'traceback': True, 
} 
call_command('cl_update_index', *args, **kwargs) 

Nếu một cuộc tranh cãi là required nó cần phải được thông qua năm qua *args. **kwargs bỏ qua trình phân tích cú pháp, khiến cho nó phản đối về các đối số bị thiếu.


Tôi đã tải xuống phiên bản django mới nhất, nhưng chưa cài đặt.Nhưng đây là một mô phỏng của call_command rằng nên kiểm tra các tùy chọn gọi điện thoại:

import argparse 

def call_command(name, *args, **options): 
    """ 
    Calls the given command, with the given options and args/kwargs. 
    standalone simulation of django.core.mangement call_command 
    """ 
    command = name 
    """ 
    .... 
    """ 
    # Simulate argument parsing to get the option defaults (see #10080 for details). 
    parser = command.create_parser('', name) 
    if command.use_argparse: 
     # Use the `dest` option name from the parser option 
     opt_mapping = {sorted(s_opt.option_strings)[0].lstrip('-').replace('-', '_'): s_opt.dest 
         for s_opt in parser._actions if s_opt.option_strings} 
     arg_options = {opt_mapping.get(key, key): value for key, value in options.items()} 
     defaults = parser.parse_args(args=args) 
     defaults = dict(defaults._get_kwargs(), **arg_options) 
     # Move positional args out of options to mimic legacy optparse 
     args = defaults.pop('args',()) 
    else: 
     # Legacy optparse method 
     defaults, _ = parser.parse_args(args=[]) 
     defaults = dict(defaults.__dict__, **options) 
    if 'skip_checks' not in options: 
     defaults['skip_checks'] = True 

    return command.execute(*args, **defaults) 

class BaseCommand(): 
    def __init__(self): 
     self.use_argparse = True 
     self.stdout= sys.stdout 
     self.stderr=sys.stderr 
    def execute(self, *args, **kwargs): 
     self.handle(*args, **kwargs) 
    def handle(self, *args, **kwargs): 
     print('args: ', args) 
     print('kwargs: ', kwargs) 
    def create_parser(self, *args, **kwargs): 
     parser = argparse.ArgumentParser() 
     self.add_arguments(parser) 
     return parser 
    def add_arguments(self, parser): 
     parser.add_argument('--type', required=True) 
     parser.add_argument('--update', action='store_true') 
     parser.add_argument('--optional', default='default') 
     parser.add_argument('foo') 
     parser.add_argument('args', nargs='*') 

if __name__=='__main__': 

    testcmd = BaseCommand() 
    # testcmd.execute('one','tow', three='four') 

    call_command(testcmd, '--type','typevalue','foovalue', 'argsvalue', update=True) 

    args = ['--type=argvalue', 'foovalue', '1', '2'] 
    kwargs = { 
     'solr_url': 'http://127.0.0.1...', 
     'type': 'opinions', 
     'update': True, 
     'everything': True, 
    } 
    call_command(testcmd, *args, **kwargs) 

trong đó sản xuất:

python3 stack32036562.py 
args: ('argsvalue',) 
kwargs: {'optional': 'default', 'type': 'typevalue', 'update': True, 'skip_checks': True, 'foo': 'foovalue'} 
args: ('1', '2') 
kwargs: {'optional': 'default', 'update': True, 'foo': 'foovalue', 'type': 'opinions', 'skip_checks': True, 'everything': True, 'solr_url': 'http://127.0.0.1...'} 

Với một loạt các cuống, tôi có thể làm clCommand của bạn làm việc với BaseCommand của tôi, và sau đây cuộc gọi hoạt động:

clupdate = Command() 
args = ['--type','opinions','--solr-url','dummy'] 
kwargs = { 
    'solr_url': 'http://127.0.0.1:8983/solr/collection1', 
    #'type': 'opinions', 
    'update': True, 
    'everything': True, 
    'do_commit': True, 
    'traceback': True, 
} 
call_command(clupdate, *args, **kwargs) 

thực hiện một bài hát everything.

Running in update mode... 
everything 
args: () 
options: {'type': 'opinions', 'query': None, 'solr_url': 'http://127.0.0.1:8983/solr/collection1', 'items': None, 'do_commit': True, 'update': True, 'delete': False, 'datetime': None, 'optimize': False, 'skip_checks': True, 'everything': True, 'traceback': True} 
+0

Vâng, các tài liệu không tuyệt vời, nhưng tôi đã thử cả hai cách. – mlissner

+1

Dựa trên việc đọc mã 'django', tôi nghĩ rằng các đối số' required' cần phải được đưa ra thông qua '* args', chứ không phải' ** kwargs'. – hpaulj

+0

Câu trả lời hay, mặc dù tôi vẫn không thể vượt qua bất cứ điều gì như một dict. Ngay cả những thứ bạn nói * nên * làm việc? Không làm việc. Cách duy nhất này làm việc cho tôi là để vượt qua tất cả mọi thứ như một danh sách. – mlissner

Các vấn đề liên quan