I'm trying to update a Django project from version 3.2.10 to 4.0.1

When running the tests, I'm getting this error:

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'.

The code that's raising the error is:

class ProcessFlinksTransactionsJob(Job):
objects = ProcessFlinksTransactionsJobManager()

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

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

How would I go about fixing this error?

2

There are 2 best solutions below

0
On

Found a relevant thread on DjangoProject, see it here.

As a comment says:

It's an intended change, see 73b1b225ce1a3318d4478f90cc0db0a260aba3aa. This error was added to prevent misconfigurations when values for the same fields are passed in args and kwargs as in your case. I'd recommend moving this logic to the save().

I have nothing else but to agree with Mariusz Felisiak :)

0
On

I stumbled upon this today, and while Mariusz's solution makes sense, sometimes you may use the object without saving it.

This is triggered because when a model is loaded from db, it is instantiated by new = cls(*values). If your init sets a field with a keyword, the change introduced in #22640 will raise the error when an object is created from the db (as it is probably in your tests).

The fix that worked for me is to set the fields on init only if there are not args.

In your case it would be:

class ProcessFlinksTransactionsJob(Job):
    objects = ProcessFlinksTransactionsJobManager()

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

This way the objects gets instantiated correctly when loaded from db and can be created programmatically and keep the current behaviour.

Hope it works for you! :)