Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30740 closed Bug (invalid)

collectstatic tries to connect to database

Reported by: PaszaVonPomiot Owned by: nobody
Component: contrib.staticfiles Version: 2.1
Severity: Normal Keywords: collectstatic
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In models.py I have a model AbcRules with attribute that queries another model:

ASSIGN_CHOICES = [team for team in sorted(set(People.objects.all().values_list("SquadName", flat=True)))]

For some reason during collectstatic execution Django tries to connect to database which fails on RedHat. The same collectstatic command will work on Windows. The problem is somewhat similar to:
https://code.djangoproject.com/ticket/17656
and maybe
https://code.djangoproject.com/ticket/23514

---> Collecting Django static files ...
Traceback (most recent call last):
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 216, in ensure_connection
    self.connect()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 194, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/opt/app-root/lib/python3.6/site-packages/sql_server/pyodbc/base.py", line 307, in get_new_connection
    timeout=timeout)
pyodbc.OperationalError: ('HYT00', '[HYT00] [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "./manage.py", line 11, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/app-root/lib/python3.6/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/opt/app-root/lib/python3.6/site-packages/django/core/management/__init__.py", line 357, in execute
    django.setup()
  File "/opt/app-root/lib/python3.6/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/opt/app-root/lib/python3.6/site-packages/django/apps/registry.py", line 112, in populate
    app_config.import_models()
  File "/opt/app-root/lib/python3.6/site-packages/django/apps/config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "/opt/app-root/lib64/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 "/opt/app-root/src/vs/models.py", line 1543, in <module>
    class AbcRules(models.Model):
  File "/opt/app-root/src/vs/models.py", line 1562, in TscmRules
    ASSIGN_CHOICES = [team for team in sorted(set(People.objects.all().values_list("SquadName", flat=True)))]
  File "/opt/app-root/lib/python3.6/site-packages/django/db/models/query.py", line 268, in __iter__
    self._fetch_all()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/models/query.py", line 1186, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/opt/app-root/lib/python3.6/site-packages/django/db/models/query.py", line 176, in __iter__
    for row in compiler.results_iter(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size):
  File "/opt/app-root/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 "/opt/app-root/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1052, in execute_sql
    sql, params = self.as_sql()
  File "/opt/app-root/lib/python3.6/site-packages/sql_server/pyodbc/compiler.py", line 176, in as_sql
    supports_offset_clause = self.connection.sql_server_version >= 2012
  File "/opt/app-root/lib/python3.6/site-packages/django/utils/functional.py", line 37, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/opt/app-root/lib/python3.6/site-packages/sql_server/pyodbc/base.py", line 390, in sql_server_version
    with self.temporary_connection() as cursor:
  File "/opt/rh/rh-python36/root/usr/lib64/python3.6/contextlib.py", line 81, in __enter__
    return next(self.gen)
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 577, in temporary_connection
    with self.cursor() as cursor:
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 255, in cursor
    return self._cursor()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 232, in _cursor
    self.ensure_connection()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 216, in ensure_connection
    self.connect()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 216, in ensure_connection
    self.connect()
  File "/opt/app-root/lib/python3.6/site-packages/django/db/backends/base/base.py", line 194, in connect
    self.connection = self.get_new_connection(conn_params)
  File "/opt/app-root/lib/python3.6/site-packages/sql_server/pyodbc/base.py", line 307, in get_new_connection
    timeout=timeout)
django.db.utils.OperationalError: ('HYT00', '[HYT00] [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

Change History (5)

comment:1 by Claude Paroz, 5 years ago

Component: GIScontrib.staticfiles
Resolution: invalid
Status: newclosed

I would say that querying the database at module import time is a very bad idea, so you should find a different way to populate your choices attribute (the choices might be better suited at the form level).

comment:2 by PaszaVonPomiot, 5 years ago

Resolution: invalid
Status: closednew

As suggested I have moved querying part from models.py to admin.py and used ModelForm class to modify form in admin panel. Unfortunately I got the same error during collectstatic:

class AbcRulesForm(ModelForm):
    ASSIGN_CHOICES = [(team, team) for team in sorted(set(People.objects.all().values_list("SquadName", flat=True)))]
    assignment = forms.ChoiceField(choices=ASSIGN_CHOICES)

class AbcRules2(admin.ModelAdmin):
    form = AbcRulesForm

admin.site.register(AbcRules, AbcRules2)
File "/opt/app-root/src/vs/admin.py", line 51, in <module>
class AbcRulesForm(ModelForm):
File "/opt/app-root/src/vs/admin.py", line 52, in AbcRulesForm
ASSIGN_CHOICES = [(team, team) for team in sorted(set(People.objects.all().values_list("SquadName", flat=True)))]
...
django.db.utils.OperationalError: ('HYT00', '[HYT00] [unixODBC][Microsoft][ODBC Driver 13 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

Above solution works on Windows but fails on RedHat.
Again 'collectstatic' should never connect to database.

comment:3 by Claude Paroz, 5 years ago

Resolution: fixed
Status: newclosed

Being in admin.py or in models.py, the query is still run at import time.

Please use wiki:TicketClosingReasons/UseSupportChannels

comment:4 by Claude Paroz, 5 years ago

Resolution: fixedinvalid

comment:5 by PaszaVonPomiot, 5 years ago

The solution was to use ModelChoiceField in admin.py for ModelForm class that was used in AdminModel class for that particular model.

Note: See TracTickets for help on using tickets.
Back to Top