Не могу запросить SQL Server из django, используя django-pyodbc
Я пытаюсь синхронизировать базу данных SQL Server 2008 R2, работающую удаленно на IIS 7, с приложением django 1.6, работающим на python 3.3 в Windows 7, используя manage.py syncdb
, Однако я встречаюсь с ошибкой,
TypeError: The first argument to execute must be a string or unicode query.
У меня установлен django-pyodbc 0.2.3 и pyodbc 3.0.7 с моим settings.py DATABASES
как,
{
'default': {
'ENGINE': 'django_pyodbc',
'HOST': '...',
'NAME': '...',
'OPTIONS': {
'host_is_server': True
}
}
}
Как вы можете догадаться, USER
а также PASSWORD
опущены, так как мне нужно Integrated_Security=Yes
а также Trusted_Connection=Yes
для связи. OPTIONS
кажется, должен быть непустым из-за способа, которым django-pyodbc инициализирует класс DatabaseWrapper
, даже если host_is_server
не имеет отношения к Windows.
Полная ошибка, которую я получаю:
Traceback (most recent call last):
File "Z:\python\ns_reports_server\manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\__init__.py", line 399, in execute_from_command_line
utility.execute()
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\__init__.py", line 392, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\base.py", line 242, in run_from_argv
self.execute(*args, **options.__dict__)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\base.py", line 285, in execute
output = self.handle(*args, **options)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\base.py", line 415, in handle
return self.handle_noargs(**options)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\core\management\commands\syncdb.py", line 57, in handle_noargs
cursor = connection.cursor()
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\db\backends\__init__.py", line 157, in cursor
cursor = self.make_debug_cursor(self._cursor())
File "C:\Python33\lib\site-packages\django_pyodbc-0.2.3-py3.3.egg\django_pyodbc\base.py", line 290, in _cursor
File "C:\Python33\lib\site-packages\django_pyodbc-0.2.3-py3.3.egg\django_pyodbc\operations.py", line 31, in _get_sql_server_ver
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\db\backends\util.py", line 69, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "C:\Python33\lib\site-packages\django-1.6.1-py3.3.egg\django\db\backends\util.py", line 51, in execute
return self.cursor.execute(sql)
File "C:\Python33\lib\site-packages\django_pyodbc-0.2.3-py3.3.egg\django_pyodbc\base.py", line 410, in execute
TypeError: The first argument to execute must be a string or unicode query.
Если вы посмотрите на исходный код десятого вызова сверху, django_pyodbc / operations.py запрашивает соединение для версии SQL Server,
cur.execute("SELECT CAST(SERVERPROPERTY('ProductVersion') as varchar)")
Тем не менее, к концу стека вызовов этот sql для выполнения исчез. django_pyodbc / base.py имеет,
return self.cursor.execute(sql, params)
для которого первый аргумент не распознается как "запрос строки или Юникода".
Python, django и SQL Server все новые для меня, поэтому ответ может быть очевидным, но я не могу на всю жизнь решить это. Приветствия.
3 ответа
Edit: driver_supports_utf8=True, поскольку упоминание в других ответах будет правильным исправлением.
Похоже, что это проблема с django-pyodbc и Python 3.
В base.py строка 367
sql = sql.encode('utf-8')
Эта строка превращает строку в байты, что и вызывает TypeError. Поскольку вы работаете в Windows, я предполагаю, что драйвер может обрабатывать Unicode. Я предлагаю вам закомментировать строки с 364 по 367 (первые 4 в функции format_sql). Таким образом, ваши строки Unicode останутся Unicode, и вы не получите TypeError.
https://github.com/lionheart/django-pyodbc/blob/master/django_pyodbc/base.py
def format_sql(self, sql, n_params=None):
if not self.driver_supports_utf8 and isinstance(sql, text_type):
# Older FreeTDS (and other ODBC drivers?) don't support Unicode yet, so
# we need to encode the SQL clause itself in utf-8
sql = sql.encode('utf-8')
# pyodbc uses '?' instead of '%s' as parameter placeholder.
if n_params is not None:
try:
sql = sql % tuple('?' * n_params)
except:
#Todo checkout whats happening here
pass
else:
if '%s' in sql:
sql = sql.replace('%s', '?')
return sql
Я поднял проблему с django-pyodbc, которая более подробно описана.
Вы также можете исправить это в опциях конфигурации. Я боролся с этим некоторое время. Попробуйте изменить вашу БД, чтобы она была в конфигурации, как это для 1.6:
DATABASES = {
'default': {
'ENGINE': 'django_pyodbc',
'NAME': 'db_name',
'USER': 'db_user',
'PASSWORD': 'your_password',
'HOST': 'database.domain.com,1433',
'PORT': '1433',
'OPTIONS': {
'host_is_server': True,
'autocommit': True,
'unicode_results': True,
'extra_params': 'tds_version=8.0'
},
}
}
Если вы используете Windows, "extra_params" игнорируется, но делает его переносимым на Linux.
Эта проблема решена для нас, добавив 'driver_supports_utf8': True,'
'characteristics': {
'ENGINE': "django_pyodbc",
'HOST': "ourdbhost.com",
'PORT': 5555,
'NAME': "OurDB",
'USER': "ouruser",
'PASSWORD': "acoolpw",
'OPTIONS': {
'driver_supports_utf8': True,
'host_is_server': True,
'extra_params': 'TDS_Version=7.1',
},
},
работал как предложено Gri на https://github.com/lionheart/django-pyodbc/issues/47
добавление
'autocommit': True,
'unicode_results': True,
в OPTIONS
не исправил, но и ничего не сломал