4

I'm setting up my django project on a new remote server. When trying to setup the database running `python manage.py migrate' to run all migrations I get the following error:

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
    utility.execute()
  File "/usr/local/lib/python2.7/dist-packages/django/core/management/__init__.py", line 354, in execute
    django.setup()
  File "/usr/local/lib/python2.7/dist-packages/django/__init__.py", line 21, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/usr/local/lib/python2.7/dist-packages/django/apps/registry.py", line 115, in populate
    app_config.ready()
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/apps.py", line 22, in ready
    self.module.autodiscover()
  File "/usr/local/lib/python2.7/dist-packages/django/contrib/admin/__init__.py", line 23, in autodiscover
    autodiscover_modules('admin', register_to=site)
  File "/usr/local/lib/python2.7/dist-packages/django/utils/module_loading.py", line 74, in autodiscover_modules
    import_module('%s.%s' % (app_config.name, module_to_search))
  File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/home/django/kwp/app/admin.py", line 3, in <module>
    from app.views import genCustCode
  File "/home/django/kwp/app/views.py", line 6, in <module>
    from app.forms import *
  File "/home/django/kwp/app/forms.py", line 466, in <module>
    tag_choices = ((obj.id, obj.tag) for obj in BlogTag.objects.all())
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 141, in __iter__
    self._fetch_all()
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 966, in _fetch_all
    self._result_cache = list(self.iterator())
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 265, in iterator
    for row in compiler.results_iter():
  File "/usr/local/lib/python2.7/dist-packages/django/db/models/sql/compiler.py", line 700, 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 786, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 81, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/utils.py", line 94, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/utils.py", line 65, in execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python2.7/dist-packages/django/db/backends/mysql/base.py", line 128, in execute
    return self.cursor.execute(query, args)
  File "/usr/local/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 205, in execute
    self.errorhandler(self, exc, value)
  File "/usr/local/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
    raise errorclass, errorvalue
django.db.utils.ProgrammingError: (1146, "Table 'kwp_db_prod.app_blogtag' doesn't exist")

I'm not sure what the issue is but it looks like my forms.py is getting called and looking for the BlogTag table before that table exists. Why would this happen when running migrations? Any way to get around this?

Thanks for your help.

apardes
  • 4,272
  • 7
  • 40
  • 66

2 Answers2

16

There's a problem in the way your code is written, especially this line :

tag_choices = ((obj.id, obj.tag) for obj in BlogTag.objects.all())

In forms.py : you shouldn't use any QuerySet filtering in module body because it is executed when the module load, you'd rather call it in a function.

That's why your migration cannot be applied : you're trying to get data from database, using queryset, during module (forms.py) load but the table doesn't exist before migration :)

Try to comment this line and try to apply your migrations again.

But remember that this is a bad practice, if there's other lines like this one, you'd better comment them to apply migration, and best, move them into functions

Raphaël Braud
  • 1,489
  • 10
  • 14
  • 3
    Would you have any recommendations for alternative implementations? Patchwork [currently has this issue](https://github.com/getpatchwork/patchwork/blob/5b0b0b74/patchwork/forms.py#L216) and I'd like to resolve it – stephenfin May 20 '16 at 09:10
  • I've updated the answer to include a complete solution for anyone who comes across this problem and wasn't sure what the previous answer version was referring to when specifying factoring the behaviour into a function. There's also a related answer here: https://stackoverflow.com/a/39084645/6310633 – jidicula Jan 08 '21 at 14:08
0

You shouldn't be doing any QuerySet filtering in the model body. Otherwise the filtering is run upon import of the module. Since imports occur before migrations are run, this could result in the interpreter trying to make calls to a database that doesn't exist yet. This is the cause of your stack trace, throwing the exception table doesn't exist.

In the model body, the best practice is to instead set the attribute as None, then run your database call in the __init__() method for the class. See here for details:

class FooMultipleChoiceForm(forms.Form):
    foo_select = forms.ModelMultipleChoiceField(queryset=None)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['foo_select'].queryset = ...

This ensures that your database calls are only run when the object is created, and not upon import of the class or module.

jidicula
  • 3,454
  • 1
  • 17
  • 38