2014-09-25 9 views
5

ho un problema relativo ai test la mia app tra cui le migrazioni sul modelfields ForeignKey aventi un valore di default (vedi esempio qui sotto, campo modalità nel modello RuleSet).Django 1.7 Errore di migrazione sulla ForeignKey con valore di default

Non so se questo è un bug in Django 1.7 migrazioni test o se sto facendo qualcosa di sbagliato

#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) 

ho provato seguendo i passaggi della migrazione finora:

  1. creato un primo migrazione con valore predefinito (funzione)
  2. creato una migrazione iniziale senza valore predefinito e creata una seconda migrazione cambiando il campo impostando il valore predefinito

Nessuno di loro ha funzionato per me. Quindi puoi vedere che il problema non è legato alla migrazione del campo stesso. È solo correlato al fatto che esistono migrazioni per l'app.

(sovrascrivendo il metodo save sarebbe una soluzione o disabilitando le migrazioni durante i test che utilizzano questa soluzione: Disable migrations when running unit tests in Django 1.7, ma io preferirei impostando l'attributo di default)

#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'), 
     ), 
    ] 

L'uscita eseguendo: manage.py pitone prova 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. 

Tutte le idee sono benvenute

risposta

5

ho trovato una soluzione per il mio problema.

Il problema è che il database è, ovviamente, vuoto durante l'applicazione delle migrazioni. Poiché

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

utilizza

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

la funzione utilizzata per impostare il valore di default viene eseguita. Ma non c'è valore nel Database.

Ora ho aggiunto una migrazione dei dati tra la migrazione iniziale e la migrazione che aggiunge il valore predefinito.

questo sembra che:

# -*- 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), 
    ] 

e nella migrazione che aggiunge il valore di default ottiene la lista delle dipendenze viene modificato in:

dependencies = [ 
    ('myapp', '0002_auto_20140925_1458'), 
]