Обновление до Django 4.0.1 с Django 3.2.10 - сообщение об ошибке "получены как позиционные, так и ключевые аргументы для поля"

Я пытаюсь обновить проект Django с версии 3.2.10 до 4.0.1

При выполнении тестов я получаю следующую ошибку:

File "/Users/akira/Projects/work/speedy/cash_flow/jobs/bank_account/process_flinks_transactions_job.py", line 63, in __init__
    super(ProcessFlinksTransactionsJob, self).__init__(*args, **kwargs)
  File "/Users/akira/.local/share/virtualenvs/speedy-kJQJ8v9W/lib/python3.8/site-packages/django/db/models/base.py", line 446, in __init__
    raise TypeError(
TypeError: ProcessFlinksTransactionsJob() got both positional and keyword arguments for field 'name'.

Код, который вызывает ошибку, следующий:

class ProcessFlinksTransactionsJob(Job):
objects = ProcessFlinksTransactionsJobManager()

def __init__(self, *args, **kwargs):
    kwargs.update({"name": ProcessFlinksTransactionsJob.__name__})

    super(ProcessFlinksTransactionsJob, self).__init__(*args, **kwargs)

Как мне исправить эту ошибку?

Нашел соответствующую тему на DjangoProject, смотрите ее здесь.

В одном из комментариев говорится:

Это намеренное изменение, см. 73b1b225ce1a3318d4478f90cc0db0a260aba3aa. Эта ошибка была добавлена для предотвращения неправильной конфигурации, когда значения для одних и тех же полей передаются в args и kwargs, как в вашем случае. Я бы рекомендовал перенести эту логику в save().

.

Мне не остается ничего другого, как согласиться с Мариушем Фелисяком :)

Я наткнулся на это сегодня, и хотя решение Мариуша имеет смысл, иногда вы можете использовать объект без его сохранения.

Это происходит потому, что когда модель загружается из db, она инстанцируется командой new = cls(*values). Если ваш init задает поле с ключевым словом, то изменение, введенное в #22640, вызовет ошибку при создании объекта из db (как это, вероятно, происходит в ваших тестах).

Исправление, которое сработало для меня - это установка полей на init только если нет args.

В вашем случае это будет:

class ProcessFlinksTransactionsJob(Job):
    objects = ProcessFlinksTransactionsJobManager()

    def __init__(self, *args, **kwargs):
        if not args:
             kwargs.update({"name": ProcessFlinksTransactionsJob.__name__})
        super(ProcessFlinksTransactionsJob, self).__init__(*args, **kwargs)

Таким образом, объекты будут правильно инстанцироваться при загрузке из db и могут быть созданы программно с сохранением текущего поведения.

Надеемся, что это сработает для вас! :)

Back to Top