Tuesday, July 6, 2021

Unit testing migrations [Was: Related model 'company.user' cannot be resolved]

It seems I have to meddle with history and persuade the testing harness
that my custom user model has been in the company app from the beginning
of time. See story below.

Upside is that testing will (might) start working again. Downside is
I'll go mad.

Any ideas?

Thanks

Mike

On 6/07/2021 11:40 am, Mike Dewhirst wrote:
> I moved my custom user and userprofile models from my 'common' app
> into my 'company' app by way of locking the model tables first
> (db_table = "common_user" and so on) and just plain refactoring.
>
> That has all worked sort of as expected in that Company and User
> models now appear in the company app space in the Admin which was my
> original motivation.
>
> makemigrations wanted to destroy data with delete/create models in
> order to move them and of course I couldn't let that happen. migrate
> --fake and migrate --fake-initial wouldn't work due to lots of other
> models looking for settings.AUTH_USER_MODEL which Django couldn't find
> in the company app so I finessed my own fake migrations. That also
> seemed to work and the job seemed done.
>
> BUT manage.py test now fails with "Related model 'company.user' cannot
> be resolved"
>
> StackOverflow seems to indicate my finessed migrations are at fault. I
> have tried to tweak the dependencies with no luck as follows ...
>
> # company.migrations.0005_user_userprofile.py
> ...
>     dependencies = [
>         ('auth', '0012_alter_user_first_name_max_length'),
>         ('company', '0004_auto_20210510_1431'),       # older pre move
> migration
>         ('common', '0008_auto_20210705_1740'),        # see below
>     ]
>
>     operations = [
>         migrations.CreateModel(
>             name='User',
>             fields=[
>                 ('id', models.BigAutoField(auto_created=True,
> primary_key=True, serialize=False, verbose_name='ID')),
>                 ('password', models.CharField(max_length=128,
> verbose_name='password')),
> ... etc for creating both User and UserProfile models
>
> # common.migrations.0008_auto_20210705_1740.py
> ...
>     dependencies = [
>         ('common', '0007_userprofile_job_title'),    # older pre-move
> migration
>     ]
>
>     operations = [
>         migrations.RemoveField(
>             model_name='userprofile',
>             name='company',
>         ),
>         migrations.RemoveField(
>             model_name='userprofile',
>             name='user',
>         ),
>         migrations.DeleteModel(
>             name='User',
>         ),
>         migrations.DeleteModel(
>             name='UserProfile',
>         ),
>     ]
>
>
> Django 3.2.5, Python 3.8
>
> I feel I should have zigged when I should've zagged. Thanks for any
> suggestions
>
> Mike
>
> Traceback (most recent call last):
>   File "manage.py", line 21, in <module>
>     main()
>   File "manage.py", line 17, in main
>     execute_from_command_line(sys.argv)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\__init__.py",
> line 419, in execute_from_command_line
>     utility.execute()
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\__init__.py",
> line 413, in execute
>     self.fetch_command(subcommand).run_from_argv(self.argv)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\commands\test.py",
> line 23, in run_from_argv
>     super().run_from_argv(argv)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\base.py",
> line 354, in run_from_argv
>     self.execute(*args, **cmd_options)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\base.py",
> line 398, in execute
>     output = self.handle(*args, **options)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\commands\test.py",
> line 55, in handle
>     failures = test_runner.run_tests(test_labels)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\test\runner.py",
> line 725, in run_tests
>     old_config = self.setup_databases(aliases=databases)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\test\runner.py",
> line 643, in setup_databases
>     return _setup_databases(
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\test\utils.py", line
> 179, in setup_databases
>     connection.creation.create_test_db(
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\base\creation.py",
> line 74, in create_test_db
>     call_command(
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\__init__.py",
> line 181, in call_command
>     return command.execute(*args, **defaults)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\base.py",
> line 398, in execute
>     output = self.handle(*args, **options)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\base.py",
> line 89, in wrapped
>     res = handle_func(*args, **kwargs)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\core\management\commands\migrate.py",
> line 244, in handle
>     post_migrate_state = executor.migrate(
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\migrations\executor.py",
> line 117, in migrate
>     state = self._migrate_all_forwards(state, plan, full_plan,
> fake=fake, fake_initial=fake_initial)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\migrations\executor.py",
> line 147, in _migrate_all_forwards
>     state = self.apply_migration(state, migration, fake=fake,
> fake_initial=fake_initial)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\migrations\executor.py",
> line 227, in apply_migration
>     state = migration.apply(state, schema_editor)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\migrations\migration.py",
> line 126, in apply
>     operation.database_forwards(self.app_label, schema_editor,
> old_state, project_state)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\migrations\operations\models.py",
> line 92, in database_forwards
>     schema_editor.create_model(model)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\base\schema.py",
> line 343, in create_model
>     sql, params = self.table_sql(model)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\base\schema.py",
> line 162, in table_sql
>     definition, extra_params = self.column_sql(model, field)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\backends\base\schema.py",
> line 215, in column_sql
>     db_params = field.db_parameters(connection=self.connection)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 1004, in db_parameters
>     return {"type": self.db_type(connection), "check":
> self.db_check(connection)}
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 1001, in db_type
>     return self.target_field.rel_db_type(connection=connection)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 897, in target_field
>     return self.foreign_related_fields[0]
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\utils\functional.py",
> line 48, in __get__
>     res = instance.__dict__[self.name] = self.func(instance)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 644, in foreign_related_fields
>     return tuple(rhs_field for lhs_field, rhs_field in
> self.related_fields if rhs_field)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\utils\functional.py",
> line 48, in __get__
>     res = instance.__dict__[self.name] = self.func(instance)
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 632, in related_fields
>     return self.resolve_related_fields()
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 936, in resolve_related_fields
>     related_fields = super().resolve_related_fields()
>   File
> "D:\Users\mike\envs\xxai\lib\site-packages\django\db\models\fields\related.py",
> line 615, in resolve_related_fields
>     raise ValueError('Related model %r cannot be resolved' %
> self.remote_field.model)
> ValueError: Related model 'company.user' cannot be resolved
>
>


--
Signed email is an absolute defence against phishing. This email has
been signed with my private key. If you import my public key you can
automatically decrypt my signature and be sure it came from me. Just
ask and I'll send it to you. Your email software can handle signing.


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/0011a532-5d56-4da1-d0f9-8626ebd2576e%40dewhirst.com.au.

No comments:

Post a Comment