向现有模型添加新字段 - django.db.utils.ProgrammingError:列{field}不存在

时间:2018-01-04 20:38:08

标签: python django postgresql django-models database-migration

models.py

我有一个Scorecard模型,其中包含一个名为Account的另一个模型的ManyToManyField:

class Scorecard(models.Model):

    ....
    name = models.CharField(max_length=100)
    accounts = models.ManyToManyField(Account)
    ...

    def __str__(self):
        return self.name

我的Account课程目前有四个字段(account_name,adwords_account_id,bingads_account_id,label)。

class Account(models.Model):

    account_name = models.CharField(max_length=100)
    adwords_account_id = models.CharField(max_length=10, blank=True)
    bingads_account_id = models.CharField(max_length=15, blank=True)
    # gemini_account_id = models.CharField(max_length=15, blank=True)
    label = models.CharField(max_length=30, blank=True)

    def __str__(self):
        return self.account_name

请注意,字段gemini_account_id已被注释掉。 我想将此字段添加到模型中。

如果我将gemini_account_id注释掉并运行服务器,那么一切正常。

如果我取消注释gemini_account_id并执行python manage.py makemigrations

(venv) C:\Django\scorecard>python manage.py makemigrations

完全错误

Traceback (most recent call last):
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
psycopg2.ProgrammingError: column scorecards_account.gemini_account_id does not exist
LINE 1: ...t_id", "scorecards_account"."bingads_account_id", "scorecard...
                                                             ^


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "C:\Django\venv\lib\site-packages\django\core\management\__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "C:\Django\venv\lib\site-packages\django\core\management\__init__.py", line 347, in execute
    django.setup()
  File "C:\Django\venv\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Django\venv\lib\site-packages\django\apps\registry.py", line 120, in populate
    app_config.ready()
  File "C:\Django\venv\lib\site-packages\django\contrib\admin\apps.py", line 23, in ready
    self.module.autodiscover()
  File "C:\Django\venv\lib\site-packages\django\contrib\admin\__init__.py", line 26, in autodiscover
    autodiscover_modules('admin', register_to=site)
  File "C:\Django\venv\lib\site-packages\django\utils\module_loading.py", line 47, in autodiscover_modules
    import_module('%s.%s' % (app_config.name, module_to_search))
  File "C:\Django\venv\lib\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 "C:\Django\scorecard\scorecards\admin.py", line 2, in <module>
    from scorecards.forms import (ScorecardAdminForm, AccountAdminForm, ReportTypeAdminForm,
  File "C:\Django\scorecard\scorecards\forms.py", line 5, in <module>
    class ScorecardAdminForm(forms.ModelForm):
  File "C:\Django\scorecard\scorecards\forms.py", line 7, in ScorecardAdminForm
    class Meta:
  File "C:\Django\scorecard\scorecards\forms.py", line 15, in Meta
    attrs={'class': 'wide-select'}),
  File "C:\Django\venv\lib\site-packages\django\forms\widgets.py", line 558, in __init__
    self.choices = list(choices)
  File "C:\Django\venv\lib\site-packages\django\db\models\query.py", line 272, in __iter__
    self._fetch_all()
  File "C:\Django\venv\lib\site-packages\django\db\models\query.py", line 1179, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "C:\Django\venv\lib\site-packages\django\db\models\query.py", line 54, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "C:\Django\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1063, in execute_sql
    cursor.execute(sql, params)
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 100, in execute
    return super().execute(sql, params)
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "C:\Django\venv\lib\site-packages\django\db\utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "C:\Django\venv\lib\site-packages\django\db\backends\utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: column scorecards_account.gemini_account_id does not exist
LINE 1: ...t_id", "scorecards_account"."bingads_account_id", "scorecard...
                                                             ^

好。所以这告诉我数据库中不存在gemini_account_id列。我对此的反应是“那是因为我试图添加它!”。我以为makemigrations可以帮助我做到这一点吗?

将新字段添加到另一个模型(Account)的“ManyToManyField”的现有模型(Scorecard)的适当的操作步骤是什么?

Picture of PostGreSQL Table

我的数据库是PostgrSQL。

我尝试了什么:

  1. python manage.py makemigrations scorecards:与上面相同的错误
  2. 重命名了迁移文件夹,使用 init .py创建了空文件夹:与上面相同的错误。
  3. 我完成了之前的每次迁移,一次删除一次并运行makemigrations:每次都出现与上面相同的错误
  4. 我看过的其他帖子:

    This one似乎是最接近的,但建议是“迁移落后于特定模式”。

    更新 这是 forms.py ScorecardAdminForm

    class ScorecardAdminForm(forms.ModelForm):
    
        class Meta:
    
            model = Scorecard
            fields = '__all__'
            #fields = ('name', 'accounts', 'report_type', 'date_range')
            widgets = {
                'name': forms.TextInput(attrs={'class': 'wide-select'}),
                'accounts': forms.SelectMultiple(choices=Account.objects.all(),
                                                 attrs={'class': 'wide-select'}),
                'report_type': forms.Select(attrs={'class': 'wide-select'}),
                'date_range': forms.Select(attrs={'class': 'wide-select'}),
                'time_segment': forms.Select(attrs={'class': 'wide-select'})
            }
    
        def clean(self):
            cleaned_data = super().clean()
            date_range = cleaned_data.get('date_range')
            start_date = cleaned_data.get('start_date')
            end_date = cleaned_data.get('end_date')
    
            if date_range == 'CUSTOM_DATE':
                if start_date is None or end_date is None:
                    raise ValidationError(
                        "Start or end can't be left blank "
                        "when report type is custom date range."
                    )
    

    我认为通过在admin.py和forms.py中注释掉所有内容然后跟随this answer,我确实已经完成了迁移。 ScorecardAdminForm中的原因是什么?也许提升ValidationError部分?抱歉,我是一只迷失的小羊羔。

1 个答案:

答案 0 :(得分:0)

该字段通过管理表单引用。从ScorecardAdminForm中删除引用并首先进行迁移。