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:
在使用schemamigration向数据库添加列时,我遇到了一个问题。这个字段是“is_”,是我的应用程序“上传”中的视频模型的布尔值。在运行迁移时,我得到以下内容:
....:~/..../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.
知道它为什么不让我迁移吗?当我特别使用-add-field时也会发生同样的情况。
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?
我认为问题可能出在另一个应用程序(“score”,你可以在回溯中看到)中引用视频对象的一个ForeignKey。如果是这样的话,什么才是迁移模型的正确方法呢?
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?
我找到了一种变通方法,即在“score”中注释出有问题的外国关键字行,像往常一样进行迁移,最后取消注释行,而不迁移“score”本身。这是可行的,但并不优雅,而且如果应用程序之间有很多外国键的话,会很麻烦。正如我之前所问的,有什么方法可以自动避免这种情况,而不必使用新字段编辑模型的ForeignKey ?
2 个解决方案
#1
5
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.
问题不在于你有一个外国人指向你正在迁移的模型。这是一个很常见的情况,而南方肯定会处理好。真正的问题是你在FK声明中做了非常糟糕的事情。
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.
这个默认声明将在导入时执行查询并获取它的第一个值。在导入时执行的事情是一个很大的禁忌(特别是查询)。因此,当South导入模型以便它能够对模型进行内省并生成schemamigration,就会执行Video.objects.all()。但是由于视频模型被更改(您刚刚添加了一个新字段),这在DB中还不存在,Django的ORM引发了一个错误。
If you really want to set that as your default value, then use a callable instead
如果您真的想要将其设置为默认值,那么请使用callable
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?
注意:虽然我首先想不出一个好的理由,将第一个视频记录设置为视频FK的默认值。你想做什么?
#2
5
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.
不确定这是不是你想要的但是我遇到了一个类似的问题,这就是解决它的方法。如果您更改了模型,并且没有正确地更新数据库,那么您将得到相同的错误。运行syncdb不会更改已经创建的表,因此在加载任何其他数据之前,必须重置数据库。
python manage.py reset (app_name)
Then sync your database again and you should be good.
然后再次同步数据库,你应该做得很好。
python manage.py syncdb
#1
5
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.
问题不在于你有一个外国人指向你正在迁移的模型。这是一个很常见的情况,而南方肯定会处理好。真正的问题是你在FK声明中做了非常糟糕的事情。
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.
这个默认声明将在导入时执行查询并获取它的第一个值。在导入时执行的事情是一个很大的禁忌(特别是查询)。因此,当South导入模型以便它能够对模型进行内省并生成schemamigration,就会执行Video.objects.all()。但是由于视频模型被更改(您刚刚添加了一个新字段),这在DB中还不存在,Django的ORM引发了一个错误。
If you really want to set that as your default value, then use a callable instead
如果您真的想要将其设置为默认值,那么请使用callable
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?
注意:虽然我首先想不出一个好的理由,将第一个视频记录设置为视频FK的默认值。你想做什么?
#2
5
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.
不确定这是不是你想要的但是我遇到了一个类似的问题,这就是解决它的方法。如果您更改了模型,并且没有正确地更新数据库,那么您将得到相同的错误。运行syncdb不会更改已经创建的表,因此在加载任何其他数据之前,必须重置数据库。
python manage.py reset (app_name)
Then sync your database again and you should be good.
然后再次同步数据库,你应该做得很好。
python manage.py syncdb