使用南迁移时Django报错:“字段列表”中的未知列

发布于 2024-11-26 19:14:44 字数 3690 浏览 1 评论 0原文

使用 schemamigration 将列添加到数据库时遇到问题。有问题的字段“is_flaged”是一个布尔值,属于我的应用程序“上传”中的视频模型。运行迁移时,我得到以下信息:

....:~/..../webapp$ python manage.py schemamigration upload --auto
Traceback (most recent call last):
  File "manage.py", line 14, in <module>
    execute_manager(settings)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 219, in execute
    self.validate()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/validation.py", line 36, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 146, in get_app_errors
    self._populate()
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 61, in _populate
    self.load_app(app_name, True)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 78, in load_app
    models = import_module('.models', app_name)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/home/..../score/models.py", line 43, in <module>
    class Score(models.Model):          # matches with one specific user and one specific video
  File "/home/..../score/models.py", line 45, in Score
    video = models.ForeignKey(Video, default=Video.objects.all()[0])    # default value shouldn't end up in real objects
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 190, in __getitem__
    return list(qs)[0]
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 84, in __len__
    self._result_cache.extend(self._iter)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 273, in iterator
    for row in compiler.results_iter():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 680, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 166, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/pymodules/python2.7/MySQLdb/connections.py", line 35, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1054, "Unknown column 'upload_video.is_flagged' in 'field list'")

知道为什么它不允许我迁移吗?当我专门使用 --add-field 时也会发生同样的情况。

我认为问题可能在于另一个应用程序中的外键(“分数”,正如您在回溯中看到的那样)引用了视频对象。如果是这种情况,迁移其他应用程序中的外键引用的模型的正确方法是什么?

更新

我找到了一个解决方法,即注释掉“score”中有问题的ForeignKey行,照常运行迁移,最后取消注释该行,而无需迁移“score”本身。这可行,但并不优雅,而且如果应用程序之间有很多外键,就会很麻烦。正如我之前问的,有什么方法可以自动避免这种情况,而不必将带有外键的模型编辑为带有新字段的模型?

I'm running into a problem when using schemamigration to add a column to my database. The field in question, 'is_flagged', is a boolean belonging to the Video model in my app 'upload'. When running the migration, I get the following:

....:~/..../webapp$ python manage.py schemamigration upload --auto
Traceback (most recent call last):
  File "manage.py", line 14, in <module>
    execute_manager(settings)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 438, in execute_manager
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 379, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 191, in run_from_argv
    self.execute(*args, **options.__dict__)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 219, in execute
    self.validate()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/validation.py", line 36, in get_validation_errors
    for (app_name, error) in get_app_errors().items():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 146, in get_app_errors
    self._populate()
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 61, in _populate
    self.load_app(app_name, True)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/loading.py", line 78, in load_app
    models = import_module('.models', app_name)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/home/..../score/models.py", line 43, in <module>
    class Score(models.Model):          # matches with one specific user and one specific video
  File "/home/..../score/models.py", line 45, in Score
    video = models.ForeignKey(Video, default=Video.objects.all()[0])    # default value shouldn't end up in real objects
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 190, in __getitem__
    return list(qs)[0]
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 84, in __len__
    self._result_cache.extend(self._iter)
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 273, in iterator
    for row in compiler.results_iter():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 680, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/util.py", line 34, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 86, in execute
    return self.cursor.execute(query, args)
  File "/usr/lib/pymodules/python2.7/MySQLdb/cursors.py", line 166, in execute
    self.errorhandler(self, exc, value)
  File "/usr/lib/pymodules/python2.7/MySQLdb/connections.py", line 35, in defaulterrorhandler
    raise errorclass, errorvalue
_mysql_exceptions.OperationalError: (1054, "Unknown column 'upload_video.is_flagged' in 'field list'")

Any idea why it won't let me migrate? The same happens when I specifically use --add-field too.

I think the problem might lie in a ForeignKey in another app ('score', as you can see in the traceback) which references the Video object. If that's the case, what is the proper way to migrate models which are referenced by ForeignKeys in other apps?

Update

I found a workaround, which is to comment out the offending ForeignKey line in 'score', run the migration as usual, and finally uncomment the line, without ever migrating 'score' itself. This works, but it's not elegant, and would be cumbersome if there were many ForeignKeys between apps. As I asked before, is there any way to avoid this automatically, without having to edit the model with the ForeignKey to the model with the new field?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

爱冒险 2024-12-03 19:14:44

问题不在于您有一个 ForeignKey 指向您正在迁移的模型。这是一种非常常见的情况,South 绝对可以很好地处理这种情况。
真正的问题是你在 FK 声明中做了一些非常非常糟糕的事情。

video = models.ForeignKey(Video, default=Video.objects.all()[0])

此默认声明将在导入时执行查询并获取它的第一个值。在导入时执行的事情是一个很大的禁忌(尤其是查询)。
因此,当 South 导入模型以便能够内省它们并生成架构迁移时,Video.objects.all() 就会被执行。但是,由于 Video 模型已更改(您刚刚添加了一个新字段),而该模型在数据库中尚不存在,因此 Django 的 ORM 会引发错误。

如果您确实想将其设置为默认值,请使用可调用

def get_default_video():
     return Video.objects.all()[0]

...
video = models.ForeignKey(Video, default=get_default_video)

注意:虽然我一开始就想不出一个好的理由,但为了设置第一个Video 记录为视频 FK 的默认值。你想做什么?

The problem is not that you have a ForeignKey pointed to the model you are migrating. That is a very common situation, and South definitely deals fine with that.
The real problem is that you are doing something very very bad in that FK declaration.

video = models.ForeignKey(Video, default=Video.objects.all()[0])

This default declaration is going to execute the query at import time and take it's first value. Things that execute at import time are a big no-no (especially a query).
So what happens is, when South imports the models so that it can introspect them and generate the schemamigration, Video.objects.all() is executed. But because Video model was changed (you've just added a new field), which doesn't exist yet in DB, Django's ORM raises an error.

If you really want to set that as your default value, then use a callable instead

def get_default_video():
     return Video.objects.all()[0]

...
video = models.ForeignKey(Video, default=get_default_video)

Note: Although I cannot think of a good reason in the first place, for setting the first Video record as default value for the video FK. What are you trying to do?

苍风燃霜 2024-12-03 19:14:44

不确定这是否正是您正在寻找的,但我遇到了类似的问题,这就是解决它的方法。如果您更改了模型并且没有正确更新数据库,那么您将收到相同的错误。运行syncdb不会更改已创建的表,因此在加载任何其他数据之前,必须重置数据库。

python manage.py reset (app_name)

然后再次同步你的数据库,你应该就可以了。

python manage.py syncdb 

Not sure if this is exactly what you are looking for but I ran into a similar problem and this is what fixed it. If you have changed you models and have not properly updated the database then you will get the same error. Running syncdb won't change tables that have already been created so before you can load any additional data you must reset the database.

python manage.py reset (app_name)

Then sync your database again and you should be good.

python manage.py syncdb 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文