Django:我的测试迁移引发了Key Error,但正常迁移是可以的。发生了什么问题以及如何解决?

问题描述 投票:3回答:1

Django测试迁移引发关键错误

我收到密钥错误,但仅当我执行python manage.py test时发生,而当我执行python manage.py makemigrationspython manage.py migrate时则没有。

关于如何解决此问题的任何建议?

python manage.py test apps/userprofile
Creating test database for alias 'default'...
Got an error creating the test database: database "test_financetracker" already exists

Type 'yes' if you would like to try deleting the test database 'test_financetracker', or 'no' to cancel: yes
Destroying old test database for alias 'default'...
Traceback (most recent call last):
  File "manage.py", line 16, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 23, in run_from_argv
    super().run_from_argv(argv)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/commands/test.py", line 53, in handle
    failures = test_runner.run_tests(test_labels)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/test/runner.py", line 629, in run_tests
    old_config = self.setup_databases(aliases=databases)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/test/runner.py", line 554, in setup_databases
    self.parallel, **kwargs
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/test/utils.py", line 174, in setup_databases
    serialize=connection.settings_dict.get('TEST', {}).get('SERIALIZE', True),
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/db/backends/base/creation.py", line 72, in create_test_db
    run_syncdb=True,
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/__init__.py", line 148, in call_command
    return command.execute(*args, **defaults)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/base.py", line 83, in wrapped
    res = handle_func(*args, **kwargs)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 234, in handle
    fake_initial=fake_initial,
  File "/Users/financetracker/myvenv/lib/python3.7/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 "/Users/financetracker/myvenv/lib/python3.7/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 "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/db/migrations/executor.py", line 245, in apply_migration
    state = migration.apply(state, schema_editor)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/db/migrations/migration.py", line 114, in apply
    operation.state_forwards(self.app_label, project_state)
  File "/Users/financetracker/myvenv/lib/python3.7/site-packages/django/db/migrations/operations/fields.py", line 165, in state_forwards
    for name, instance in state.models[app_label, self.model_name_lower].fields:
KeyError: ('hourly_rate', 'hourlyrate')

这是来自models.py文件的相关(我认为)hourly_rates python类:

class HourlyRate(TimeStampedModel):
    # TODO remove user PK as it will no longer be used.
    user = models.OneToOneField(
        User, blank=True, null=True, on_delete=models.CASCADE)
    upload = models.ForeignKey(
        'hourly_rate.Upload', blank=True, null=True, on_delete=models.CASCADE)
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE)

    name = models.CharField(max_length=255)
    timekeeper = models.CharField(verbose_name='Timekeeper ID', max_length=20,
                                  blank=True)  # is required, but blank = True and null = True for backwards compatiblity.
    classification = models.CharField(max_length=20, choices=CLASSIFICATIONS)
    years_of_experience = models.PositiveIntegerField(blank=True,
                                                      null=True)  # is required, but blank = True and null = True for backwards compatiblity.
    hourly_rate = models.PositiveIntegerField(default=1)
    currency = models.ForeignKey(Currency, on_delete=models.CASCADE)

    status = models.CharField(choices=UPLOAD_STATUSES,
                              default='requested', max_length=255)
    fiscal_year = models.PositiveIntegerField(choices=YEARS, default=2017)

    def __str__(self):
        return '{}, {}'.format(self.name, self.timekeeper)

    def status_and_date(self):
        """Return the status and date of the upload, if an upload is available. Else: return status. Might change this later to -"""
        if self.upload:
            return self.upload.status_and_date
        else:
            return self.status  # idea, change to: "-"

    class Meta:
        ordering = ('user__userprofile__name', '-id',)
        verbose_name = 'Timekeeper rate'

这是目录流,尽管为了简单起见,我删除了很多文件,所以如果缺少某些东西,问一下。

manage.py
config
├── __init__.py
├── __pycache__
│   └── __init__.cpython-37.pyc
├── alpha
│   ├── nginx
│   └── supervisor
├── default.conf
├── demo
│   ├── nginx
│   └── supervisor
├── settings
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   ├── base.cpython-37.pyc
│   │   ├── defaults.cpython-37.pyc
│   │   └── development.cpython-37.pyc
│   ├── alpha.py
│   ├── base.py
│   ├── defaults.py
│   ├── demo.py
│   ├── development.py
│   ├── local.py
│   ├── production.py
│   └── staging.py
├── staging
│   ├── nginx
│   └── supervisor
└── wsgi.py
apps
└── report
└── hourly_rate
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-37.pyc
    │   ├── admin.cpython-37.pyc
    │   ├── apps.cpython-37.pyc
    │   ├── filters.cpython-37.pyc
    │   ├── forms.cpython-37.pyc
    │   ├── helpers.cpython-37.pyc
    │   ├── models.cpython-37.pyc
    │   ├── urls.cpython-37.pyc
    │   └── views.cpython-37.pyc
    ├── admin.py
    ├── filters.py
    ├── forms.py
    ├── helpers.py
    ├── migrations
    │   ├── 0001_initial.py
    │   ├── 0002_auto_20170424_1735.py
    │   ├── 0003_auto_20170424_1738.py
    │   ├── 0004_auto_20170424_1818.py
    │   ├── 0005_auto_20170424_1917.py
    │   ├── 0006_auto_20170424_2302.py
    │   ├── 0007_auto_20170504_1948.py
    │   ├── 0008_auto_20170513_1412.py
    │   ├── 0009_auto_20170613_1726.py
    │   ├── 0010_auto_20171115_1051.py
    │   ├── 0011_auto_20180311_1223.py
    │   ├── 0012_auto_20190801_1703.py
    │   ├── __init__.py
    │   └── __pycache__
    │       ├── 0001_initial.cpython-37.pyc
    │       ├── 0002_auto_20170424_1735.cpython-37.pyc
    │       ├── 0003_auto_20170424_1738.cpython-37.pyc
    │       ├── 0004_auto_20170424_1818.cpython-37.pyc
    │       ├── 0005_auto_20170424_1917.cpython-37.pyc
    │       ├── 0006_auto_20170424_2302.cpython-37.pyc
    │       ├── 0007_auto_20170504_1948.cpython-37.pyc
    │       ├── 0008_auto_20170513_1412.cpython-37.pyc
    │       ├── 0009_auto_20170613_1726.cpython-37.pyc
    │       ├── 0010_auto_20171115_1051.cpython-37.pyc
    │       ├── 0011_auto_20180311_1223.cpython-37.pyc
    │       ├── 0012_auto_20190801_1703.cpython-37.pyc
    │       └── __init__.cpython-37.pyc
    ├── models.py
    ├── urls.py
    └── views.py

Django版本是2.2.9

迁移文件是许多

,并且是自动的。这是十二个中的前两个:

initial

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ('customer', '0002_historicalbillingaddress_historicalentity'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Upload',
            fields=[
                ('id', models.AutoField(verbose_name='ID',
                                        serialize=False, auto_created=True, primary_key=True)),
                ('created', models.DateTimeField(null=True, editable=False)),
                ('updated', models.DateTimeField(null=True, editable=False)),
                ('excel_file', models.FileField(help_text=b'Kies het door u ingevulde bestand.', upload_to=b'uploads',
                                                verbose_name=b'Upload')),
                ('period', models.DateField(null=True, blank=True)),
                ('status', models.CharField(default=b'upload failed', max_length=255,
                                            choices=[(b'upload failed', b'upload failed'), (b'requested', b'requested'),
                                                     (b'rejected', b'rejected'), (b'approved', b'approved')])),
                ('customer', models.ForeignKey(
                    to='customer.Customer', on_delete=models.CASCADE)),
                ('user', models.ForeignKey(verbose_name=b'uploaded by user',
                                           to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
            ],
            options={
                'abstract': False,
            },
        ),
    ]


秒,从现在开始是自动的,但是这个已经被编辑


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ('vendor', '0008_auto_20170417_1656'),
        ('customer', '0002_historicalbillingaddress_historicalentity'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('currency', '0001_initial'),
        ('hourly_rate', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='HourlyRate',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('created', models.DateTimeField(null=True, editable=False)),
                ('updated', models.DateTimeField(null=True, editable=False)),
                ('name', models.CharField(max_length=255, blank=True)),
                ('classification', models.CharField(max_length=20,
                                                    choices=[(b'AS', b'AS'), (b'OC', b'OC'), (b'OT', b'OT'),
                                                             (b'PL', b'PL'), (b'PT', b'PT')])),
                ('hourly_rate', models.PositiveIntegerField()),
                ('status', models.CharField(default=b'approved', max_length=255,
                                            choices=[(b'upload failed', b'upload failed'), (b'requested', b'requested'),
                                                     (b'rejected', b'rejected'), (b'approved', b'approved')])),
                ('period', models.DateField(null=True, blank=True)),
                ('currency', models.ForeignKey(to='currency.Currency', on_delete=models.CASCADE)),
                ('customer', models.ForeignKey(default=1, to='customer.Customer', on_delete=models.CASCADE)),
            ],
            options={
                'ordering': ('user__userprofile__name', '-id'),
            },
        ),
        migrations.AlterModelOptions(
            name='upload',
            options={'ordering': ['-id']},
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='upload',
            field=models.ForeignKey(blank=True, to='hourly_rate.Upload', null=True, on_delete=models.CASCADE),
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='user',
            field=models.OneToOneField(null=True, blank=True, to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE),
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='vendor',
            field=models.ForeignKey(blank=True, to='vendor.Vendor', null=True, on_delete=models.CASCADE),
        ),
    ]

    def apply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

    def unapply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

编辑前的第二秒

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models
from django.conf import settings


class Migration(migrations.Migration):

    dependencies = [
        ('vendor', '0008_auto_20170417_1656'),
        ('customer', '0002_historicalbillingaddress_historicalentity'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
        ('currency', '0001_initial'),
        ('hourly_rate', '0001_initial'),
    ]

    operations = [
        migrations.CreateModel(
            name='HourlyRate',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('created', models.DateTimeField(null=True, editable=False)),
                ('updated', models.DateTimeField(null=True, editable=False)),
                ('name', models.CharField(max_length=255, blank=True)),
                ('classification', models.CharField(max_length=20, choices=[(b'AS', b'AS'), (b'OC', b'OC'), (b'OT', b'OT'), (b'PL', b'PL'), (b'PT', b'PT')])),
                ('hourly_rate', models.PositiveIntegerField()),
                ('status', models.CharField(default=b'approved', max_length=255, choices=[(b'upload failed', b'upload failed'), (b'requested', b'requested'), (b'rejected', b'rejected'), (b'approved', b'approved')])),
                ('period', models.DateField(null=True, blank=True)),
                ('currency', models.ForeignKey(to='currency.Currency')),
                ('customer', models.ForeignKey(default=1, to='customer.Customer')),
            ],
            options={
                'ordering': ('user__userprofile__name', '-id'),
            },
        ),
        migrations.AlterModelOptions(
            name='upload',
            options={'ordering': ['-id']},
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='upload',
            field=models.ForeignKey(blank=True, to='hourly_rate.Upload', null=True),
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='user',
            field=models.OneToOneField(null=True, blank=True, to=settings.AUTH_USER_MODEL),
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='vendor',
            field=models.ForeignKey(blank=True, to='vendor.Vendor', null=True),
        ),
    ]

    def apply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

    def unapply(self, project_state, schema_editor, collect_sql=False):
        return project_state.clone()

第三

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):
    dependencies = [
        ('hourly_rate', '0002_auto_20170424_1735'),
    ]

    operations = [
        migrations.RemoveField(
            model_name='hourlyrate',
            name='period',
        ),
        migrations.RemoveField(
            model_name='upload',
            name='period',
        ),
        migrations.AddField(
            model_name='hourlyrate',
            name='fiscal_year',
            field=models.PositiveIntegerField(default=2017,
                                              choices=[(2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020),
                                                       (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)]),
        ),
        migrations.AddField(
            model_name='upload',
            name='fiscal_year',
            field=models.PositiveIntegerField(default=2017,
                                              choices=[(2017, 2017), (2018, 2018), (2019, 2019), (2020, 2020),
                                                       (2021, 2021), (2022, 2022), (2023, 2023), (2024, 2024)]),
        ),
    ]

debugging on the line it breaks at

调试引发错误的行。

enter image description here是迁移吗?是代码吗?

谢谢

[Django测试迁移会引发关键错误,但只有在执行python manage.py测试时才会出现关键错误,而在执行python manage.py makemigrations或python manage.py migration时则不会。任何建议如何...

django python-3.x postgresql migration
1个回答
0
投票

因此,感谢@brunodesthuilliers,我检查了git blame,发现“自动”迁移实际上是手动编辑的。为了解决问题,我把它们全部扔掉了,现在我可以继续进行测试写作了。谢谢您的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.