长话短说:我使用tests.py来覆盖我的django代码,我修改了很多代码和模型(18次迁移),一切都很好。
但是在上次更改和迁移(添加了一些布尔文件)后,我的测试开始在第8次迁移时崩溃
django.db.utils.OperationalError: no such column: tickets_ticket.ActionRequired
在网站上的Apache中,我可以使用新列,使用它添加模型,一切看起来都不错,但测试失败
有人可以告诉我,出了什么问题以及如何纠正它?
长篇故事:
Models.py:
def Ticket_generateUniqueID(related=''):
retval=''
sanitized=''
......
# --- now find unique value
while True:
passNo += 1
retval = generateID()
try:
t = Ticket.objects.get(ticket_number=retval)
pass
except ObjectDoesNotExist:
return retval
....
class Ticket(models.Model):
....
ticket_number = models.CharField(max_length=100,default=Ticket_generateUniqueID,help_text=u"ID of ticket")
ActionRequired = models.BooleanField(default=False,help_text=u"Action Required")
def save(self): # {{{
if not self.id and not self.ticket_number: self.ticket_number=Ticket_generateUniqueID('OTH')
retval=super(Ticket,self).save()
return retval
和我的测试会话(应该从没有test_ *数据库开始)
$ ./manage.py test -v3
settings ...
Creating test database for alias 'default' (':memory:')...
Operations to perform:
Synchronize unmigrated apps: django_extensions
Apply all migrations: admin, tickets, contenttypes, auth, sessions
Synchronizing apps without migrations:
Running pre-migrate handlers for application admin
Running pre-migrate handlers for application auth
Running pre-migrate handlers for application contenttypes
Running pre-migrate handlers for application sessions
Running pre-migrate handlers for application django_extensions
Running pre-migrate handlers for application tickets
Creating tables...
Installing custom SQL...
Installing indexes...
Loading 'initial_data' fixtures...
Checking '/home/gilhad/GIT/kompitech_test/src/kompitech_test' for fixtures...
No fixture 'initial_data' in '/home/gilhad/GIT/kompitech_test/src/kompitech_test'.
Installed 0 object(s) from 0 fixture(s)
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying sessions.0001_initial... OK
Applying tickets.0001_initial... OK
Applying tickets.0002_importedemail_is_new... OK
Applying tickets.0003_auto_20151102_1642... OK
Applying tickets.0004_auto_20151116_1633... OK
Applying tickets.0005_auto_20151118_0756... OK
Applying tickets.0006_emailpart_originalfilename... OK
Applying tickets.0007_ticket_fv_ticket_id... OK
Applying tickets.0008_auto_20151123_1430...Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 377, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/lib/python2.7/dist-packages/django/core/management/commands/test.py", line 50, in run_from_argv
super(Command, self).run_from_argv(argv)
File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 288, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/lib/python2.7/dist-packages/django/core/management/commands/test.py", line 71, in execute
super(Command, self).execute(*args, **options)
File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/usr/lib/python2.7/dist-packages/django/core/management/commands/test.py", line 88, in handle
failures = test_runner.run_tests(test_labels)
File "/usr/lib/python2.7/dist-packages/django/test/runner.py", line 147, in run_tests
old_config = self.setup_databases()
File "/usr/lib/python2.7/dist-packages/django/test/runner.py", line 109, in setup_databases
return setup_databases(self.verbosity, self.interactive, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/test/runner.py", line 299, in setup_databases
serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE", True),
File "/usr/lib/python2.7/dist-packages/django/db/backends/creation.py", line 377, in create_test_db
test_flush=True,
File "/usr/lib/python2.7/dist-packages/django/core/management/__init__.py", line 115, in call_command
return klass.execute(*args, **defaults)
File "/usr/lib/python2.7/dist-packages/django/core/management/base.py", line 338, in execute
output = self.handle(*args, **options)
File "/usr/lib/python2.7/dist-packages/django/core/management/commands/migrate.py", line 161, in handle
executor.migrate(targets, plan, fake=options.get("fake", False))
File "/usr/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 68, in migrate
self.apply_migration(migration, fake=fake)
File "/usr/lib/python2.7/dist-packages/django/db/migrations/executor.py", line 102, in apply_migration
migration.apply(project_state, schema_editor)
File "/usr/lib/python2.7/dist-packages/django/db/migrations/migration.py", line 108, in apply
operation.database_forwards(self.app_label, schema_editor, project_state, new_state)
File "/usr/lib/python2.7/dist-packages/django/db/migrations/operations/fields.py", line 139, in database_forwards
schema_editor.alter_field(from_model, from_field, to_field)
File "/usr/lib/python2.7/dist-packages/django/db/backends/schema.py", line 457, in alter_field
self._alter_field(model, old_field, new_field, old_type, new_type, old_db_params, new_db_params, strict)
File "/usr/lib/python2.7/dist-packages/django/db/backends/sqlite3/schema.py", line 202, in _alter_field
self._remake_table(model, alter_fields=[(old_field, new_field)])
File "/usr/lib/python2.7/dist-packages/django/db/backends/sqlite3/schema.py", line 139, in _remake_table
self.create_model(temp_model)
File "/usr/lib/python2.7/dist-packages/django/db/backends/schema.py", line 213, in create_model
definition, extra_params = self.column_sql(model, field)
File "/usr/lib/python2.7/dist-packages/django/db/backends/schema.py", line 125, in column_sql
default_value = self.effective_default(field)
File "/usr/lib/python2.7/dist-packages/django/db/backends/schema.py", line 175, in effective_default
default = field.get_default()
File "/usr/lib/python2.7/dist-packages/django/db/models/fields/__init__.py", line 719, in get_default
return self.default()
File "/home/gilhad/GIT/kompitech_test/src/kompitech_test/tickets/models.py", line 56, in Ticket_generateUniqueID
t = Ticket.objects.get(ticket_number=retval)
File "/usr/lib/python2.7/dist-packages/django/db/models/manager.py", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 351, in get
num = len(clone)
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 122, in __len__
self._fetch_all()
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 966, in _fetch_all
self._result_cache = list(self.iterator())
File "/usr/lib/python2.7/dist-packages/django/db/models/query.py", line 265, in iterator
for row in compiler.results_iter():
File "/usr/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 700, in results_iter
for rows in self.execute_sql(MULTI):
File "/usr/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 786, in execute_sql
cursor.execute(sql, params)
File "/usr/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/usr/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
return self.cursor.execute(sql, params)
File "/usr/lib/python2.7/dist-packages/django/db/backends/sqlite3/base.py", line 485, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such column: tickets_ticket.ActionRequired
请注意,它几乎不是最后一次迁移,而且每次测试之前都会进行测试
$ ls -1 tickets/migrations/*py
tickets/migrations/0001_initial.py
tickets/migrations/0002_importedemail_is_new.py
tickets/migrations/0003_auto_20151102_1642.py
tickets/migrations/0004_auto_20151116_1633.py
tickets/migrations/0005_auto_20151118_0756.py
tickets/migrations/0006_emailpart_originalfilename.py
tickets/migrations/0007_ticket_fv_ticket_id.py
tickets/migrations/0008_auto_20151123_1430.py
tickets/migrations/0009_auto_20151123_1718.py
tickets/migrations/0010_auto_20151123_1928.py
tickets/migrations/0011_auto_20151124_0938.py
tickets/migrations/0012_auto_20151125_1351.py
tickets/migrations/0013_auto_20151125_1406.py
tickets/migrations/0014_configemailcompany.py
tickets/migrations/0015_auto_20151126_1435.py
tickets/migrations/0016_configemailcompany_we.py
tickets/migrations/0017_auto_20151126_1730.py
tickets/migrations/0018_auto_20151127_1103.py
tickets/migrations/0019_auto_20151130_0934.py
tickets/migrations/__init__.py
失败的迁移:
migrations.AlterField(
model_name='ticket',
name='by_user',
field=models.ForeignKey(related_name='changed_records_of_ticket', blank=True, to=settings.AUTH_USER_MODEL, help_text='Last modification was by this user (autofilled)', null=True, db_index=False),
preserve_default=True,
),
migrations.AlterField(
model_name='ticket',
name='ticket_number',
field=models.CharField(default=tickets.models.Ticket_generateUniqueID, help_text='ID of ticket', max_length=100),
preserve_default=True,
),
(以及其他模型中许多其他by_user更改)
答案 0 :(得分:4)
问题是用于获取默认值的Ticket_generateUniqueID
方法是尝试获取尚未创建迁移的列。
try:
t = Ticket.objects.get(ticket_number=retval)
pass
except ObjectDoesNotExist:
return retval
在这种情况下,我认为您可以通过更改方法来使用exists()
而不是get()
来避免此问题。
if Ticket.objects.filter(ticket_number=retval).exists():
pass
else:
return retval
如果无法重写默认方法,则修复起来会比较棘手。我相信您必须在导致错误的迁移之前添加数据迁移,并在那里设置字段值。在数据迁移中,您可以使用Ticket = apps.get_model('myapp', 'Ticket')
。然后,您就可以毫无错误地运行Ticket.objects.get()
。
答案 1 :(得分:0)
只有一个更新:当我删除所有迁移并将它们重新创建为一个简单时,我的测试开始失败:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionRoute",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
因为我的测试创建(并没有保存)在加载夹具之前的票证对象,所以我在while循环之前添加了这个健全性测试:
django.db.utils.OperationalError: no such table: tickets_ticket