Search code examples
django

Initial local Django mysql database


I have joined a team working on a Django project, and I am trying to setup the local mysql database schema. This project has existed for a long time, so there are existing migrations.

I have created the empty database in mysql, but when I try to apply migrations to create the schema, it complains that the tables don't exist yet.

$ ./manage.py migrate

Traceback (most recent call last):
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
    res = self._query(query)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 374, in _do_query
    db.query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 277, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1146, "Table 'api_test.headset_product' doesn't exist")

I've also tried syncdb, migrate --run-syncdb, and makemigrations with the same results. I've also tried loaddata with our fixtures, with the same results.

I've read Django : Table doesn't exist, but I didn't drop tables in this case (no tables have ever existed), and I don't want to recreate all the migrations (I'm not the only person on this project).

I have a related project that uses a local postgresql database, and it doesn't seem to have this problem. I can run migrate and it does just what I expect, so it feels that I've run into a problem specific to this codebase, but we aren't certain how to debug it.


"full output of makemigrations, including the full typed command."

$ ./manage.py makemigrations
[WARNING] statsd not configured

[WARNING] SMTP not configured; emails will not be sent

[WARNING] V1 database access not configured

Traceback (most recent call last):
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
    res = self._query(query)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 374, in _do_query
    db.query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 277, in query
    _mysql.connection.query(self, query)
_mysql_exceptions.ProgrammingError: (1146, "Table 'reign_api_test.headset_product' doesn't exist")

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

Traceback (most recent call last):
  File "./manage.py", line 14, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/__init__.py", line 371, in execute_from_command_line
    utility.execute()
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/__init__.py", line 365, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/base.py", line 288, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/base.py", line 332, in execute
    self.check()
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/base.py", line 364, in check
    include_deployment_checks=include_deployment_checks,
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/management/base.py", line 351, in _run_checks
    return checks.run_checks(**kwargs)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/checks/registry.py", line 73, in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/checks/urls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/core/checks/urls.py", line 23, in check_resolver
    return check_method()
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/urls/resolvers.py", line 397, in check
    for pattern in self.url_patterns:
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/utils/functional.py", line 36, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/urls/resolvers.py", line 536, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/utils/functional.py", line 36, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/urls/resolvers.py", line 529, in urlconf_module
    return import_module(self.urlconf_name)
  File "/Users/rnapier/.pyenv/versions/3.6.6/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/Users/rnapier/clients/Jaybird/Source/reign-api/reign_api/reign_api/urls.py", line 13, in <module>
    import newsfeed.urls
  File "/Users/rnapier/clients/Jaybird/Source/reign-api/reign_api/newsfeed/urls.py", line 2, in <module>
    from newsfeed import views
  File "/Users/rnapier/clients/Jaybird/Source/reign-api/reign_api/newsfeed/views.py", line 15, in <module>
    from newsfeed import models, serializers
  File "/Users/rnapier/clients/Jaybird/Source/reign-api/reign_api/newsfeed/serializers.py", line 27, in <module>
    class NewsfeedSubscriptionSerializer(serializers.Serializer):
  File "/Users/rnapier/clients/Jaybird/Source/reign-api/reign_api/newsfeed/serializers.py", line 28, in NewsfeedSubscriptionSerializer
    PRODUCTS = [f for f in headset.models.Product.objects.values_list("name", flat=True)]
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/models/query.py", line 272, in __iter__
    self._fetch_all()
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/models/query.py", line 1179, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/models/query.py", line 178, in __iter__
    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1017, in results_iter
    results = self.execute_sql(MULTI, chunked_fetch=chunked_fetch, chunk_size=chunk_size)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1066, in execute_sql
    cursor.execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/django/db/backends/mysql/base.py", line 71, in execute
    return self.cursor.execute(query, args)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 250, in execute
    self.errorhandler(self, exc, value)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 50, in defaulterrorhandler
    raise errorvalue
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 247, in execute
    res = self._query(query)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 411, in _query
    rowcount = self._do_query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/cursors.py", line 374, in _do_query
    db.query(q)
  File "/Users/rnapier/.pyenv/versions/api-3.6.6/lib/python3.6/site-packages/MySQLdb/connections.py", line 277, in query
    _mysql.connection.query(self, query)
django.db.utils.ProgrammingError: (1146, "Table 'reign_api_test.headset_product' doesn't exist")

"model structure for headset_product"

class Product(models.Model):
    """
    products supported by the Headset API
    """

    name = models.CharField(max_length=128, unique=True)

    def __str__(self) -> str:
        return "<Product {s.id} {s.name}>".format(s=self)

    __repr__ = __str__

Solution

  • The problem is in reign_api/newsfeed/serializers.py, which is trying to make a query at class or module level. This should always be avoided in Django, as the query will be run at first import - before the migrations on a new system will have a chance to run. But this will be causing other problems too, in that that query will only be executed once per process, and will therefore not update when new data is added or changed.

    Your colleagues should fix this problem, either by refactoring to move the query into a method, or probably better by using a more appropriate serializer field that takes a queryset and does the query when called.