2017-01-22 59 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. 推,部署。