Django 1.7 Migration error for foreign key with default value

I have a problem testing my application, including migration to ForeignKey modelfields with a default value (see example below, field mode in the RuleSet model).

I do not know if there was a bug in Django 1.7 for testing migration or if I am doing something wrong

#models.py: RULE_SET_MODE__ACTIVE = "Active" def default_mode(): return RuleSetMode.objects.get(name=RULE_SET_MODE__ACTIVE) class RuleSetMode(models.Model): name = models.CharField(max_length=30) description = models.CharField(max_length=255) class RuleSet(models.Model): name = models.CharField(max_length=30, unique=True) description = models.CharField(max_length=255) mode = models.ForeignKey(RuleSetMode, default=default_mode) 

I tried to complete the following migration steps:

  • initial migration created with default value (function)
  • created an initial migration without a default value and created a second migration by changing the field, setting a default value

None of them worked for me. Thus, you can see that the problem is not related to the migration of the field itself. This is simply due to the fact that there are migrations for the application.

(Overriding the save method would be a solution or disabling migration during tests using this solution: Disable migration when running unit tests in Django 1.7 , but I would prefer setting the default attribute)

 #migrations file (altering the existing field): # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations import myapp.models class Migration(migrations.Migration): dependencies = [ ('myapp', '0001_initial'), ] operations = [ migrations.AlterField( model_name='ruleset', name='mode', field=models.ForeignKey(default=myapp.models.default_mode, to='myapp.RuleSetMode'), ), ] 

The output is: python manage.py test myapp:

 Creating test database for alias 'default'... Traceback (most recent call last): File "manage.py", line 16, in <module> execute_from_command_line(sys.argv) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/__init__.py", line 385, in execute_from_command_line utility.execute() File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/__init__.py", line 377, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/commands/test.py", line 50, in run_from_argv super(Command, self).run_from_argv(argv) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/base.py", line 288, in run_from_argv self.execute(*args, **options.__dict__) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/commands/test.py", line 71, in execute super(Command, self).execute(*args, **options) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/base.py", line 338, in execute output = self.handle(*args, **options) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/commands/test.py", line 88, in handle failures = test_runner.run_tests(test_labels) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/test/runner.py", line 147, in run_tests old_config = self.setup_databases() File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/test/runner.py", line 109, in setup_databases return setup_databases(self.verbosity, self.interactive, **kwargs) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/test/runner.py", line 299, in setup_databases serialize=connection.settings_dict.get("TEST_SERIALIZE", True), File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/creation.py", line 374, in create_test_db test_flush=True, File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/__init__.py", line 115, in call_command return klass.execute(*args, **defaults) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/base.py", line 338, in execute output = self.handle(*args, **options) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/core/management/commands/migrate.py", line 160, in handle executor.migrate(targets, plan, fake=options.get("fake", False)) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/migrations/executor.py", line 63, in migrate self.apply_migration(migration, fake=fake) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/migrations/executor.py", line 97, in apply_migration migration.apply(project_state, schema_editor) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/migrations/migration.py", line 107, in apply operation.database_forwards(self.app_label, schema_editor, project_state, new_state) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/migrations/operations/fields.py", line 131, in database_forwards schema_editor.alter_field(from_model, from_field, to_field) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/schema.py", line 509, in alter_field self._alter_field(model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/sqlite3/schema.py", line 183, in _alter_field self._remake_table(model, alter_fields=[(old_field, new_field)]) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/sqlite3/schema.py", line 121, in _remake_table self.create_model(temp_model) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/schema.py", line 208, in create_model definition, extra_params = self.column_sql(model, field) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/schema.py", line 120, in column_sql default_value = self.effective_default(field) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/backends/schema.py", line 170, in effective_default default = field.get_default() File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/models/fields/related.py", line 1711, in get_default field_default = super(ForeignKey, self).get_default() File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/models/fields/__init__.py", line 719, in get_default return self.default() File "/usr/local/lib/python2.7/dev-packages/kiola/kiola_alfred/models.py", line 33, in default_mode return RuleSetMode.objects.get(name=RULE_SET_MODE__ACTIVE) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/models/manager.py", line 92, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/home/cgossy/venvs/django-1.7/local/lib/python2.7/site-packages/Django-1.7-py2.7.egg/django/db/models/query.py", line 357, in get self.model._meta.object_name) myapp.models.DoesNotExist: RuleSetMode matching query does not exist. 

Any ideas are welcome

+5
source share
1 answer

I found a solution for my problem.

The problem is that the database is, of course, empty while the migrations are applied. Because

 migrations.AlterField( model_name='ruleset', name='mode', field=models.ForeignKey(default=myapp.models.default_mode, to='myapp.RuleSetMode'), ), 

uses

 models.ForeignKey(default=myapp.models.default_mode, to='myapp.RuleSetMode') 

the function used to set the default value is executed. But there is no value in the database.

Now I have added a data migration between the initial migration and the migration, which adds a default value.

It looks like this:

 # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations def set_default_values(apps, schema_editor): # We can't import the Person model directly as it may be a newer # version than this migration expects. We use the historical version. import myapp.const as const RuleSetMode = apps.get_model("myapp", "RuleSetMode") RuleSetMode.objects.get_or_create(name=const.RULE_SET_MODE__ACTIVE) class Migration(migrations.Migration): dependencies = [ ('myapp', '0001_initial'), ] operations = [ migrations.RunPython(set_default_values), ] 

and in a migration that adds a default value, it gets a list of dependencies:

 dependencies = [ ('myapp', '0002_auto_20140925_1458'), ] 
+5
source

Source: https://habr.com/ru/post/1203370/


All Articles