2017-01-22 57 views
0

我正面临着我的一个django模型的奇怪情况。 我使用Django 1.10.3与python 3.5.2。django迁移不可能因为字段默认值中的错误?

的模型看起来像这样(为了清楚而简化):

class Report(models.Model): 
    date = models.FieldDate() 
    def fieldA_default(self): 
     return MyObject.objects.filter(date=self.date).count() 
    fieldA = models.IntegerField(default=fieldA_default) 

我有创建模型,并增加了该领域,通过使用./manage.py makemigrations django的自动生成的初始迁移。

我将此代码提交给我的git仓库,并将其部署到我的生产服务器,但实际上并未使用该模型(数据库中没有Report对象)。 我刚刚发现此代码不正确(django set default value of a model field to a self attribute),并决定替代save()

但是,当我更改默认从fieldA_default0,运行./manage.py makemigrations因为它试图运行旧的默认值功能fieldA_default失败。在尝试了几个选项后,我最终决定完全删除模型。但这不起作用,因为makemigrations仍然试图运行相同的功能。

这里是makemigrations回溯时,我只需删除模式:

Traceback (most recent call last): 
    File "./manage.py", line 22, in <module> 
    execute_from_command_line(sys.argv) 
    File "venv/lib/python3.5/site-packages/django/core/management/__init__.py", line 367, in execute_from_command_line 
    utility.execute() 
    File "venv/lib/python3.5/site-packages/django/core/management/__init__.py", line 359, in execute 
    self.fetch_command(subcommand).run_from_argv(self.argv) 
    File "venv/lib/python3.5/site-packages/django/core/management/base.py", line 294, in run_from_argv 
    self.execute(*args, **cmd_options) 
    File "venv/lib/python3.5/site-packages/django/core/management/base.py", line 345, in execute 
    output = self.handle(*args, **options) 
    File "venv/lib/python3.5/site-packages/django/core/management/commands/makemigrations.py", line 95, in handle 
    loader = MigrationLoader(None, ignore_no_migrations=True) 
    File "venv/lib/python3.5/site-packages/django/db/migrations/loader.py", line 52, in __init__ 
    self.build_graph() 
    File "venv/lib/python3.5/site-packages/django/db/migrations/loader.py", line 197, in build_graph 
    self.load_disk() 
    File "venv/lib/python3.5/site-packages/django/db/migrations/loader.py", line 108, in load_disk 
    migration_module = import_module("%s.%s" % (module_name, migration_name)) 
    File "venv/lib/python3.5/importlib/__init__.py", line 126, in import_module 
    return _bootstrap._gcd_import(name[level:], package, level) 
    File "<frozen importlib._bootstrap>", line 986, in _gcd_import 
    File "<frozen importlib._bootstrap>", line 969, in _find_and_load 
    File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked 
    File "<frozen importlib._bootstrap>", line 673, in _load_unlocked 
    File "<frozen importlib._bootstrap_external>", line 665, in exec_module 
    File "<frozen importlib._bootstrap>", line 222, in _call_with_frames_removed 
    File "xxx/reporting/migrations/0001_initial.py", line 9, in <module> 
    class Migration(migrations.Migration): 
    File "xxx/reporting/migrations/0001_initial.py", line 22, in Migration 
    ('fieldA', models.IntegerField(default=reporting.models.Report.fieldA_default)), 
AttributeError: module 'reporting.models' has no attribute 'Report' 

我有几个问题:

  • 为什么Django的运行,即使我这个“老”的代码删除模型?
  • 我是如何设法将这个无效代码放入没有Django尖叫的迁移中的?
  • 我该如何解决这种情况,以免打破我的生产服务器?我完全放弃模型并重建模型并没有问题,但我似乎没有被允许这样做。
+0

你有没有尝试过的应用程序迁移到零,删除迁移,并再次运行'makemigrations'? – schwobaseggl

+0

我需要的信息进行调试,请进入你的数据库表django_migrations,并检查是否为您的应用程序的“0001_initial”行存在。将此添加到您的帖子中。 – Fian

+0

@schwobaseggl它看起来像你的建议的工作。我跑'./manage.py情况下迁移报告zero'随后'./manage.py makemigrations reporting'和我没有错误。谢谢你的帮助!如果你添加这个作为答案,我会接受:) –

回答

1

为什么Django运行这个“旧”代码,即使我删除模型?

由于模型和方法的迁移文件仍然引用0001_initial.py

但是,当我更改默认从fieldA_default为0,运行./manage.py makemigrations,因为它试图运行失败旧的默认值函数fieldA_default。

我假设,在您重置该字段的默认值后,您删除了 - 现在已过时 - 方法fieldA_default。如上所述,这种方法在最初的迁移中被引用,现在它将被打破。

我怎么设法让该无效代码为迁移,而Django的尖叫我吗?

创建迁移时,代码无效。通过简单的向前迁移无法处理模型上的某些更改。你的情况:

  • 删除模型时,它被引用并在迁移文件导入(这本身只是一个Python模块不能只导入不存在的类)

  • 相同去除默认方法。

一两件事你可以做的时候你的模型代码是搞砸或与您的迁移/ db和makemigrations不会从当前的工作状态同步,如下:

  1. python manage.py migrate app_name zero # undo all existing migrations of app
  2. 从应用程序中删除所有迁移文件。或者,如果你已经在数据库中有价值的数据,可以撤销他们一个接一个,看看第3步已经工作

  3. python manage.py makemigrations app_name # new start from clean sheet

这是很容易在开发过程中,可以是考虑迁移挤压的替代选择,但如果您已经在db中拥有生产数据,那么显然是最后的选择。但在这种情况下,应该应用模式的变化与照顾和考虑呢:)

0
  1. 手动删除所有涉及您的迁移报告
  2. 从数据库中删除报告表
  3. 运行Python manage.py makemigrations。它将为报告创建新的迁移。
  4. 推,部署。