magic-removal: Various cleanup and moving, with respect to the recent django.core.db -> django.db move

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1637 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2005-12-14 06:24:32 +00:00
parent 394ad9aa7f
commit aecff3e245
15 changed files with 356 additions and 371 deletions

View File

@ -360,7 +360,7 @@ class _FileCache(_SimpleCache):
############# #############
import base64 import base64
from django.core.db import db, DatabaseError from django.db import connection, DatabaseError
from datetime import datetime from datetime import datetime
class _DBCache(_Cache): class _DBCache(_Cache):
@ -380,7 +380,7 @@ class _DBCache(_Cache):
self._cull_frequency = 3 self._cull_frequency = 3
def get(self, key, default=None): def get(self, key, default=None):
cursor = db.cursor() cursor = connection.cursor()
cursor.execute("SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s" % self._table, [key]) cursor.execute("SELECT cache_key, value, expires FROM %s WHERE cache_key = %%s" % self._table, [key])
row = cursor.fetchone() row = cursor.fetchone()
if row is None: if row is None:
@ -388,14 +388,14 @@ class _DBCache(_Cache):
now = datetime.now() now = datetime.now()
if row[2] < now: if row[2] < now:
cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key]) cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key])
db.commit() connection.commit()
return default return default
return pickle.loads(base64.decodestring(row[1])) return pickle.loads(base64.decodestring(row[1]))
def set(self, key, value, timeout=None): def set(self, key, value, timeout=None):
if timeout is None: if timeout is None:
timeout = self.default_timeout timeout = self.default_timeout
cursor = db.cursor() cursor = connection.cursor()
cursor.execute("SELECT COUNT(*) FROM %s" % self._table) cursor.execute("SELECT COUNT(*) FROM %s" % self._table)
num = cursor.fetchone()[0] num = cursor.fetchone()[0]
now = datetime.now().replace(microsecond=0) now = datetime.now().replace(microsecond=0)
@ -413,15 +413,15 @@ class _DBCache(_Cache):
# To be threadsafe, updates/inserts are allowed to fail silently # To be threadsafe, updates/inserts are allowed to fail silently
pass pass
else: else:
db.commit() connection.commit()
def delete(self, key): def delete(self, key):
cursor = db.cursor() cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key]) cursor.execute("DELETE FROM %s WHERE cache_key = %%s" % self._table, [key])
db.commit() connection.commit()
def has_key(self, key): def has_key(self, key):
cursor = db.cursor() cursor = connection.cursor()
cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s" % self._table, [key]) cursor.execute("SELECT cache_key FROM %s WHERE cache_key = %%s" % self._table, [key])
return cursor.fetchone() is not None return cursor.fetchone() is not None

View File

@ -22,9 +22,9 @@ PROJECT_TEMPLATE_DIR = os.path.join(django.__path__[0], 'conf', '%s_template')
INVALID_PROJECT_NAMES = ('django', 'test') INVALID_PROJECT_NAMES = ('django', 'test')
def _get_packages_insert(app_label): def _get_packages_insert(app_label):
from django.core.db import db from django.db import backend
return "INSERT INTO %s (%s, %s) VALUES ('%s', '%s');" % \ return "INSERT INTO %s (%s, %s) VALUES ('%s', '%s');" % \
(db.quote_name('packages'), db.quote_name('label'), db.quote_name('name'), (backend.quote_name('packages'), backend.quote_name('label'), backend.quote_name('name'),
app_label, app_label) app_label, app_label)
def _get_permission_codename(action, opts): def _get_permission_codename(action, opts):
@ -39,16 +39,16 @@ def _get_all_permissions(opts):
return perms + list(opts.permissions) return perms + list(opts.permissions)
def _get_permission_insert(name, codename, opts): def _get_permission_insert(name, codename, opts):
from django.core.db import db from django.db import backend
return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \ return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
(db.quote_name('auth_permissions'), db.quote_name('name'), db.quote_name('package'), (backend.quote_name('auth_permissions'), backend.quote_name('name'), backend.quote_name('package'),
db.quote_name('codename'), name.replace("'", "''"), opts.app_label, codename) backend.quote_name('codename'), name.replace("'", "''"), opts.app_label, codename)
def _get_contenttype_insert(opts): def _get_contenttype_insert(opts):
from django.core.db import db from django.db import backend
return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \ return "INSERT INTO %s (%s, %s, %s) VALUES ('%s', '%s', '%s');" % \
(db.quote_name('content_types'), db.quote_name('name'), db.quote_name('package'), (backend.quote_name('content_types'), backend.quote_name('name'), backend.quote_name('package'),
db.quote_name('python_module_name'), opts.verbose_name, opts.app_label, opts.module_name) backend.quote_name('python_module_name'), opts.verbose_name, opts.app_label, opts.module_name)
def _is_valid_dir_name(s): def _is_valid_dir_name(s):
return bool(re.search(r'^\w+$', s)) return bool(re.search(r'^\w+$', s))
@ -60,8 +60,8 @@ get_rel_data_type = lambda f: (f.get_internal_type() == 'AutoField') and 'Intege
def get_sql_create(mod): def get_sql_create(mod):
"Returns a list of the CREATE TABLE SQL statements for the given module." "Returns a list of the CREATE TABLE SQL statements for the given module."
from django.core import db from django.db import backend, get_creation_module, models
from django.db import models data_types = get_creation_module().DATA_TYPES
final_output = [] final_output = []
for klass in mod._MODELS: for klass in mod._MODELS:
opts = klass._meta opts = klass._meta
@ -73,9 +73,9 @@ def get_sql_create(mod):
else: else:
rel_field = f rel_field = f
data_type = f.get_internal_type() data_type = f.get_internal_type()
col_type = db.DATA_TYPES[data_type] col_type = data_types[data_type]
if col_type is not None: if col_type is not None:
field_output = [db.db.quote_name(f.column), col_type % rel_field.__dict__] field_output = [backend.quote_name(f.column), col_type % rel_field.__dict__]
field_output.append('%sNULL' % (not f.null and 'NOT ' or '')) field_output.append('%sNULL' % (not f.null and 'NOT ' or ''))
if f.unique: if f.unique:
field_output.append('UNIQUE') field_output.append('UNIQUE')
@ -83,16 +83,16 @@ def get_sql_create(mod):
field_output.append('PRIMARY KEY') field_output.append('PRIMARY KEY')
if f.rel: if f.rel:
field_output.append('REFERENCES %s (%s)' % \ field_output.append('REFERENCES %s (%s)' % \
(db.db.quote_name(f.rel.to._meta.db_table), (backend.quote_name(f.rel.to._meta.db_table),
db.db.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column))) backend.quote_name(f.rel.to._meta.get_field(f.rel.field_name).column)))
table_output.append(' '.join(field_output)) table_output.append(' '.join(field_output))
if opts.order_with_respect_to: if opts.order_with_respect_to:
table_output.append('%s %s NULL' % (db.db.quote_name('_order'), db.DATA_TYPES['IntegerField'])) table_output.append('%s %s NULL' % (backend.quote_name('_order'), data_types['IntegerField']))
for field_constraints in opts.unique_together: for field_constraints in opts.unique_together:
table_output.append('UNIQUE (%s)' % \ table_output.append('UNIQUE (%s)' % \
", ".join([db.db.quote_name(opts.get_field(f).column) for f in field_constraints])) ", ".join([backend.quote_name(opts.get_field(f).column) for f in field_constraints]))
full_statement = ['CREATE TABLE %s (' % db.db.quote_name(opts.db_table)] full_statement = ['CREATE TABLE %s (' % backend.quote_name(opts.db_table)]
for i, line in enumerate(table_output): # Combine and add commas. for i, line in enumerate(table_output): # Combine and add commas.
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');') full_statement.append(');')
@ -101,21 +101,21 @@ def get_sql_create(mod):
for klass in mod._MODELS: for klass in mod._MODELS:
opts = klass._meta opts = klass._meta
for f in opts.many_to_many: for f in opts.many_to_many:
table_output = ['CREATE TABLE %s (' % db.db.quote_name(f.get_m2m_db_table(opts))] table_output = ['CREATE TABLE %s (' % backend.quote_name(f.get_m2m_db_table(opts))]
table_output.append(' %s %s NOT NULL PRIMARY KEY,' % (db.db.quote_name('id'), db.DATA_TYPES['AutoField'])) table_output.append(' %s %s NOT NULL PRIMARY KEY,' % (backend.quote_name('id'), data_types['AutoField']))
table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \ table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \
(db.db.quote_name(opts.object_name.lower() + '_id'), (backend.quote_name(opts.object_name.lower() + '_id'),
db.DATA_TYPES[get_rel_data_type(opts.pk)] % opts.pk.__dict__, data_types[get_rel_data_type(opts.pk)] % opts.pk.__dict__,
db.db.quote_name(opts.db_table), backend.quote_name(opts.db_table),
db.db.quote_name(opts.pk.column))) backend.quote_name(opts.pk.column)))
table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \ table_output.append(' %s %s NOT NULL REFERENCES %s (%s),' % \
(db.db.quote_name(f.rel.to._meta.object_name.lower() + '_id'), (backend.quote_name(f.rel.to._meta.object_name.lower() + '_id'),
db.DATA_TYPES[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__, data_types[get_rel_data_type(f.rel.to._meta.pk)] % f.rel.to._meta.pk.__dict__,
db.db.quote_name(f.rel.to._meta.db_table), backend.quote_name(f.rel.to._meta.db_table),
db.db.quote_name(f.rel.to._meta.pk.column))) backend.quote_name(f.rel.to._meta.pk.column)))
table_output.append(' UNIQUE (%s, %s)' % \ table_output.append(' UNIQUE (%s, %s)' % \
(db.db.quote_name(opts.object_name.lower() + '_id'), (backend.quote_name(opts.object_name.lower() + '_id'),
db.db.quote_name(f.rel.to._meta.object_name.lower() + '_id'))) backend.quote_name(f.rel.to._meta.object_name.lower() + '_id')))
table_output.append(');') table_output.append(');')
final_output.append('\n'.join(table_output)) final_output.append('\n'.join(table_output))
return final_output return final_output
@ -124,9 +124,10 @@ get_sql_create.args = APP_ARGS
def get_sql_delete(mod): def get_sql_delete(mod):
"Returns a list of the DROP TABLE SQL statements for the given module." "Returns a list of the DROP TABLE SQL statements for the given module."
from django.core import db from django.db import backend, connection
try: try:
cursor = db.db.cursor() cursor = connection.cursor()
except: except:
cursor = None cursor = None
@ -135,10 +136,10 @@ def get_sql_delete(mod):
try: try:
if cursor is not None: if cursor is not None:
# Check whether the table exists. # Check whether the table exists.
cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name('django_admin_log')) cursor.execute("SELECT 1 FROM %s LIMIT 1" % backend.quote_name('django_admin_log'))
except: except:
# The table doesn't exist, so it doesn't need to be dropped. # The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback() connection.rollback()
admin_log_exists = False admin_log_exists = False
else: else:
admin_log_exists = True admin_log_exists = True
@ -150,12 +151,12 @@ def get_sql_delete(mod):
try: try:
if cursor is not None: if cursor is not None:
# Check whether the table exists. # Check whether the table exists.
cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name(klass._meta.db_table)) cursor.execute("SELECT 1 FROM %s LIMIT 1" % backend.quote_name(klass._meta.db_table))
except: except:
# The table doesn't exist, so it doesn't need to be dropped. # The table doesn't exist, so it doesn't need to be dropped.
db.db.rollback() connection.rollback()
else: else:
output.append("DROP TABLE %s;" % db.db.quote_name(klass._meta.db_table)) output.append("DROP TABLE %s;" % backend.quote_name(klass._meta.db_table))
# Output DROP TABLE statements for many-to-many tables. # Output DROP TABLE statements for many-to-many tables.
for klass in mod._MODELS: for klass in mod._MODELS:
@ -163,36 +164,36 @@ def get_sql_delete(mod):
for f in opts.many_to_many: for f in opts.many_to_many:
try: try:
if cursor is not None: if cursor is not None:
cursor.execute("SELECT 1 FROM %s LIMIT 1" % db.db.quote_name(f.get_m2m_db_table(opts))) cursor.execute("SELECT 1 FROM %s LIMIT 1" % backend.quote_name(f.get_m2m_db_table(opts)))
except: except:
db.db.rollback() connection.rollback()
else: else:
output.append("DROP TABLE %s;" % db.db.quote_name(f.get_m2m_db_table(opts))) output.append("DROP TABLE %s;" % backend.quote_name(f.get_m2m_db_table(opts)))
app_label = mod._MODELS[0]._meta.app_label app_label = mod._MODELS[0]._meta.app_label
# Delete from packages, auth_permissions, content_types. # Delete from packages, auth_permissions, content_types.
output.append("DELETE FROM %s WHERE %s = '%s';" % \ output.append("DELETE FROM %s WHERE %s = '%s';" % \
(db.db.quote_name('packages'), db.db.quote_name('label'), app_label)) (backend.quote_name('packages'), backend.quote_name('label'), app_label))
output.append("DELETE FROM %s WHERE %s = '%s';" % \ output.append("DELETE FROM %s WHERE %s = '%s';" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'), app_label)) (backend.quote_name('auth_permissions'), backend.quote_name('package'), app_label))
output.append("DELETE FROM %s WHERE %s = '%s';" % \ output.append("DELETE FROM %s WHERE %s = '%s';" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'), app_label)) (backend.quote_name('content_types'), backend.quote_name('package'), app_label))
# Delete from the admin log. # Delete from the admin log.
if cursor is not None: if cursor is not None:
cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \ cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('id'), db.db.quote_name('content_types'), (backend.quote_name('id'), backend.quote_name('content_types'),
db.db.quote_name('package')), [app_label]) backend.quote_name('package')), [app_label])
if admin_log_exists: if admin_log_exists:
for row in cursor.fetchall(): for row in cursor.fetchall():
output.append("DELETE FROM %s WHERE %s = %s;" % \ output.append("DELETE FROM %s WHERE %s = %s;" % \
(db.db.quote_name('django_admin_log'), db.db.quote_name('content_type_id'), row[0])) (backend.quote_name('django_admin_log'), backend.quote_name('content_type_id'), row[0]))
# Close database connection explicitly, in case this output is being piped # Close database connection explicitly, in case this output is being piped
# directly into a database client, to avoid locking issues. # directly into a database client, to avoid locking issues.
cursor.close() cursor.close()
db.db.close() connection.close()
return output[::-1] # Reverse it, to deal with table dependencies. return output[::-1] # Reverse it, to deal with table dependencies.
get_sql_delete.help_doc = "Prints the DROP TABLE SQL statements for the given model module name(s)." get_sql_delete.help_doc = "Prints the DROP TABLE SQL statements for the given model module name(s)."
@ -206,7 +207,7 @@ get_sql_reset.args = APP_ARGS
def get_sql_initial_data(mod): def get_sql_initial_data(mod):
"Returns a list of the initial INSERT SQL statements for the given module." "Returns a list of the initial INSERT SQL statements for the given module."
from django.core import db from django.conf.settings import DATABASE_ENGINE
output = [] output = []
app_label = mod._MODELS[0]._meta.app_label app_label = mod._MODELS[0]._meta.app_label
output.append(_get_packages_insert(app_label)) output.append(_get_packages_insert(app_label))
@ -215,7 +216,7 @@ def get_sql_initial_data(mod):
opts = klass._meta opts = klass._meta
# Add custom SQL, if it's available. # Add custom SQL, if it's available.
sql_files = [os.path.join(app_dir, opts.module_name + '.' + db.DATABASE_ENGINE + '.sql'), sql_files = [os.path.join(app_dir, opts.module_name + '.' + DATABASE_ENGINE + '.sql'),
os.path.join(app_dir, opts.module_name + '.sql')] os.path.join(app_dir, opts.module_name + '.sql')]
for sql_file in sql_files: for sql_file in sql_files:
if os.path.exists(sql_file): if os.path.exists(sql_file):
@ -234,25 +235,24 @@ get_sql_initial_data.args = APP_ARGS
def get_sql_sequence_reset(mod): def get_sql_sequence_reset(mod):
"Returns a list of the SQL statements to reset PostgreSQL sequences for the given module." "Returns a list of the SQL statements to reset PostgreSQL sequences for the given module."
from django.core import db from django.db import backend, models
from django.db import models
output = [] output = []
for klass in mod._MODELS: for klass in mod._MODELS:
for f in klass._meta.fields: for f in klass._meta.fields:
if isinstance(f, models.AutoField): if isinstance(f, models.AutoField):
output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % \ output.append("SELECT setval('%s_%s_seq', (SELECT max(%s) FROM %s));" % \
(klass._meta.db_table, f.column, db.db.quote_name(f.column), (klass._meta.db_table, f.column, backend.quote_name(f.column),
db.db.quote_name(klass._meta.db_table))) backend.quote_name(klass._meta.db_table)))
for f in klass._meta.many_to_many: for f in klass._meta.many_to_many:
output.append("SELECT setval('%s_id_seq', (SELECT max(%s) FROM %s));" % \ output.append("SELECT setval('%s_id_seq', (SELECT max(%s) FROM %s));" % \
(f.get_m2m_db_table(klass._meta), db.db.quote_name('id'), f.get_m2m_db_table(klass._meta))) (f.get_m2m_db_table(klass._meta), backend.quote_name('id'), f.get_m2m_db_table(klass._meta)))
return output return output
get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s)." get_sql_sequence_reset.help_doc = "Prints the SQL statements for resetting PostgreSQL sequences for the given model module name(s)."
get_sql_sequence_reset.args = APP_ARGS get_sql_sequence_reset.args = APP_ARGS
def get_sql_indexes(mod): def get_sql_indexes(mod):
"Returns a list of the CREATE INDEX SQL statements for the given module." "Returns a list of the CREATE INDEX SQL statements for the given module."
from django.core.db import db from django.db import backend
output = [] output = []
for klass in mod._MODELS: for klass in mod._MODELS:
for f in klass._meta.fields: for f in klass._meta.fields:
@ -260,7 +260,7 @@ def get_sql_indexes(mod):
unique = f.unique and "UNIQUE " or "" unique = f.unique and "UNIQUE " or ""
output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \ output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
(unique, klass._meta.db_table, f.column, (unique, klass._meta.db_table, f.column,
db.quote_name(klass._meta.db_table), db.quote_name(f.column))) backend.quote_name(klass._meta.db_table), backend.quote_name(f.column)))
return output return output
get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)." get_sql_indexes.help_doc = "Prints the CREATE INDEX SQL statements for the given model module name(s)."
get_sql_indexes.args = APP_ARGS get_sql_indexes.args = APP_ARGS
@ -282,13 +282,13 @@ def has_no_records(cursor):
def database_check(mod): def database_check(mod):
"Checks that everything is properly installed in the database for the given module." "Checks that everything is properly installed in the database for the given module."
from django.core import db from django.db import backend, connection
cursor = db.db.cursor() cursor = connection.cursor()
app_label = mod._MODELS[0]._meta.app_label app_label = mod._MODELS[0]._meta.app_label
# Check that the package exists in the database. # Check that the package exists in the database.
cursor.execute("SELECT 1 FROM %s WHERE %s = %%s" % \ cursor.execute("SELECT 1 FROM %s WHERE %s = %%s" % \
(db.db.quote_name('packages'), db.db.quote_name('label')), [app_label]) (backend.quote_name('packages'), backend.quote_name('label')), [app_label])
if has_no_records(cursor): if has_no_records(cursor):
# sys.stderr.write("The '%s' package isn't installed.\n" % app_label) # sys.stderr.write("The '%s' package isn't installed.\n" % app_label)
print _get_packages_insert(app_label) print _get_packages_insert(app_label)
@ -303,14 +303,14 @@ def database_check(mod):
contenttypes_seen[opts.module_name] = 1 contenttypes_seen[opts.module_name] = 1
for codename, name in perms: for codename, name in perms:
cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \ cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'), (backend.quote_name('auth_permissions'), backend.quote_name('package'),
db.db.quote_name('codename')), (app_label, codename)) backend.quote_name('codename')), (app_label, codename))
if has_no_records(cursor): if has_no_records(cursor):
# sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename)) # sys.stderr.write("The '%s.%s' permission doesn't exist.\n" % (app_label, codename))
print _get_permission_insert(name, codename, opts) print _get_permission_insert(name, codename, opts)
cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \ cursor.execute("SELECT 1 FROM %s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'), (backend.quote_name('content_types'), backend.quote_name('package'),
db.db.quote_name('python_module_name')), (app_label, opts.module_name)) backend.quote_name('python_module_name')), (app_label, opts.module_name))
if has_no_records(cursor): if has_no_records(cursor):
# sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name)) # sys.stderr.write("The '%s.%s' content type doesn't exist.\n" % (app_label, opts.module_name))
print _get_contenttype_insert(opts) print _get_contenttype_insert(opts)
@ -318,30 +318,30 @@ def database_check(mod):
# Check that there aren't any *extra* permissions in the DB that the model # Check that there aren't any *extra* permissions in the DB that the model
# doesn't know about. # doesn't know about.
cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \ cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('codename'), db.db.quote_name('auth_permissions'), (backend.quote_name('codename'), backend.quote_name('auth_permissions'),
db.db.quote_name('package')), (app_label,)) backend.quote_name('package')), (app_label,))
for row in cursor.fetchall(): for row in cursor.fetchall():
try: try:
perms_seen[row[0]] perms_seen[row[0]]
except KeyError: except KeyError:
# sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) # sys.stderr.write("A permission called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \ print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
(db.db.quote_name('auth_permissions'), db.db.quote_name('package'), (backend.quote_name('auth_permissions'), backend.quote_name('package'),
app_label, db.db.quote_name('codename'), row[0]) app_label, backend.quote_name('codename'), row[0])
# Check that there aren't any *extra* content types in the DB that the # Check that there aren't any *extra* content types in the DB that the
# model doesn't know about. # model doesn't know about.
cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \ cursor.execute("SELECT %s FROM %s WHERE %s = %%s" % \
(db.db.quote_name('python_module_name'), db.db.quote_name('content_types'), (backend.quote_name('python_module_name'), backend.quote_name('content_types'),
db.db.quote_name('package')), (app_label,)) backend.quote_name('package')), (app_label,))
for row in cursor.fetchall(): for row in cursor.fetchall():
try: try:
contenttypes_seen[row[0]] contenttypes_seen[row[0]]
except KeyError: except KeyError:
# sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0])) # sys.stderr.write("A content type called '%s.%s' was found in the database but not in the model.\n" % (app_label, row[0]))
print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \ print "DELETE FROM %s WHERE %s='%s' AND %s = '%s';" % \
(db.db.quote_name('content_types'), db.db.quote_name('package'), (backend.quote_name('content_types'), backend.quote_name('package'),
app_label, db.db.quote_name('python_module_name'), row[0]) app_label, backend.quote_name('python_module_name'), row[0])
database_check.help_doc = "Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed." database_check.help_doc = "Checks that everything is installed in the database for the given model module name(s) and prints SQL statements if needed."
database_check.args = APP_ARGS database_check.args = APP_ARGS
@ -370,32 +370,31 @@ get_admin_index.args = APP_ARGS
def init(): def init():
"Initializes the database with auth and core." "Initializes the database with auth and core."
try: try:
from django.core import db from django.db import backend, connection, models
from django.db import models
auth = models.get_app('auth') auth = models.get_app('auth')
core = models.get_app('core') core = models.get_app('core')
cursor = db.db.cursor() cursor = connection.cursor()
for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth): for sql in get_sql_create(core) + get_sql_create(auth) + get_sql_initial_data(core) + get_sql_initial_data(auth):
cursor.execute(sql) cursor.execute(sql)
cursor.execute("INSERT INTO %s (%s, %s) VALUES ('example.com', 'Example site')" % \ cursor.execute("INSERT INTO %s (%s, %s) VALUES ('example.com', 'Example site')" % \
(db.db.quote_name(core.Site._meta.db_table), db.db.quote_name('domain'), (backend.quote_name(core.Site._meta.db_table), backend.quote_name('domain'),
db.db.quote_name('name'))) backend.quote_name('name')))
except Exception, e: except Exception, e:
import traceback import traceback
sys.stderr.write("Error: The database couldn't be initialized.\n") sys.stderr.write("Error: The database couldn't be initialized.\n")
sys.stderr.write('\n'.join(traceback.format_exception(*sys.exc_info())) + "\n") sys.stderr.write('\n'.join(traceback.format_exception(*sys.exc_info())) + "\n")
try: try:
db.db.rollback() connection.rollback()
except UnboundLocalError: except UnboundLocalError:
pass pass
sys.exit(1) sys.exit(1)
else: else:
db.db.commit() connection.commit()
init.args = '' init.args = ''
def install(mod): def install(mod):
"Executes the equivalent of 'get_sql_all' in the current database." "Executes the equivalent of 'get_sql_all' in the current database."
from django.core import db from django.db import connection
from cStringIO import StringIO from cStringIO import StringIO
mod_name = mod.__name__[mod.__name__.rindex('.')+1:] mod_name = mod.__name__[mod.__name__.rindex('.')+1:]
@ -410,7 +409,7 @@ def install(mod):
sql_list = get_sql_all(mod) sql_list = get_sql_all(mod)
try: try:
cursor = db.db.cursor() cursor = connection.cursor()
for sql in sql_list: for sql in sql_list:
cursor.execute(sql) cursor.execute(sql)
except Exception, e: except Exception, e:
@ -421,9 +420,9 @@ def install(mod):
Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run. Hint: Look at the output of 'django-admin.py sqlall %s'. That's the SQL this command wasn't able to run.
The full error: %s\n""" % \ The full error: %s\n""" % \
(mod_name, mod_name, e)) (mod_name, mod_name, e))
db.db.rollback() connection.rollback()
sys.exit(1) sys.exit(1)
db.db.commit() connection.commit()
install.help_doc = "Executes ``sqlall`` for the given model module name(s) in the current database." install.help_doc = "Executes ``sqlall`` for the given model module name(s) in the current database."
install.args = APP_ARGS install.args = APP_ARGS
@ -559,15 +558,17 @@ createsuperuser.args = '[username] [email] [password] (Either all or none)'
def inspectdb(db_name): def inspectdb(db_name):
"Generator that introspects the tables in the given database name and returns a Django model, one line at a time." "Generator that introspects the tables in the given database name and returns a Django model, one line at a time."
from django.core import db from django.db import connection, get_introspection_module
from django.conf import settings from django.conf import settings
introspection_module = get_introspection_module()
def table2model(table_name): def table2model(table_name):
object_name = table_name.title().replace('_', '') object_name = table_name.title().replace('_', '')
return object_name.endswith('s') and object_name[:-1] or object_name return object_name.endswith('s') and object_name[:-1] or object_name
settings.DATABASE_NAME = db_name settings.DATABASE_NAME = db_name
cursor = db.db.cursor() cursor = connection.cursor()
yield "# This is an auto-generated Django model module." yield "# This is an auto-generated Django model module."
yield "# You'll have to do the following manually to clean this up:" yield "# You'll have to do the following manually to clean this up:"
yield "# * Rearrange models' order" yield "# * Rearrange models' order"
@ -579,13 +580,13 @@ def inspectdb(db_name):
yield '' yield ''
yield 'from django.db import models' yield 'from django.db import models'
yield '' yield ''
for table_name in db.get_table_list(cursor): for table_name in introspection_module.get_table_list(cursor):
yield 'class %s(models.Model):' % table2model(table_name) yield 'class %s(models.Model):' % table2model(table_name)
try: try:
relations = db.get_relations(cursor, table_name) relations = introspection_module.get_relations(cursor, table_name)
except NotImplementedError: except NotImplementedError:
relations = {} relations = {}
for i, row in enumerate(db.get_table_description(cursor, table_name)): for i, row in enumerate(introspection_module.get_table_description(cursor, table_name)):
column_name = row[0] column_name = row[0]
if relations.has_key(i): if relations.has_key(i):
rel = relations[i] rel = relations[i]
@ -596,7 +597,7 @@ def inspectdb(db_name):
field_desc = '%s = models.ForeignKey(%s, db_column=%r' % (column_name, rel_to, column_name) field_desc = '%s = models.ForeignKey(%s, db_column=%r' % (column_name, rel_to, column_name)
else: else:
try: try:
field_type = db.DATA_TYPES_REVERSE[row[1]] field_type = introspection_module.DATA_TYPES_REVERSE[row[1]]
except KeyError: except KeyError:
field_type = 'TextField' field_type = 'TextField'
field_type_was_guessed = True field_type_was_guessed = True
@ -786,8 +787,8 @@ runserver.args = '[optional port number, or ipaddr:port]'
def createcachetable(tablename): def createcachetable(tablename):
"Creates the table needed to use the SQL cache backend" "Creates the table needed to use the SQL cache backend"
from django.core import db from django.db import backend, get_creation_module, models
from django.db import models data_types = get_creation_module().DATA_TYPES
fields = ( fields = (
# "key" is a reserved word in MySQL, so use "cache_key" instead. # "key" is a reserved word in MySQL, so use "cache_key" instead.
models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True), models.CharField(name='cache_key', maxlength=255, unique=True, primary_key=True),
@ -797,7 +798,7 @@ def createcachetable(tablename):
table_output = [] table_output = []
index_output = [] index_output = []
for f in fields: for f in fields:
field_output = [db.db.quote_name(f.column), db.DATA_TYPES[f.get_internal_type()] % f.__dict__] field_output = [backend.quote_name(f.column), data_types[f.get_internal_type()] % f.__dict__]
field_output.append("%sNULL" % (not f.null and "NOT " or "")) field_output.append("%sNULL" % (not f.null and "NOT " or ""))
if f.unique: if f.unique:
field_output.append("UNIQUE") field_output.append("UNIQUE")
@ -806,18 +807,18 @@ def createcachetable(tablename):
if f.db_index: if f.db_index:
unique = f.unique and "UNIQUE " or "" unique = f.unique and "UNIQUE " or ""
index_output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \ index_output.append("CREATE %sINDEX %s_%s ON %s (%s);" % \
(unique, tablename, f.column, db.db.quote_name(tablename), (unique, tablename, f.column, backend.quote_name(tablename),
db.db.quote_name(f.column))) backend.quote_name(f.column)))
table_output.append(" ".join(field_output)) table_output.append(" ".join(field_output))
full_statement = ["CREATE TABLE %s (" % db.db.quote_name(tablename)] full_statement = ["CREATE TABLE %s (" % backend.quote_name(tablename)]
for i, line in enumerate(table_output): for i, line in enumerate(table_output):
full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or '')) full_statement.append(' %s%s' % (line, i < len(table_output)-1 and ',' or ''))
full_statement.append(');') full_statement.append(');')
curs = db.db.cursor() curs = connection.cursor()
curs.execute("\n".join(full_statement)) curs.execute("\n".join(full_statement))
for statement in index_output: for statement in index_output:
curs.execute(statement) curs.execute(statement)
db.db.commit() connection.commit()
createcachetable.args = "[tablename]" createcachetable.args = "[tablename]"
# Utilities for command-line script # Utilities for command-line script

View File

@ -15,5 +15,11 @@ except ImportError, e:
raise ImproperlyConfigured, "Could not load database backend: %s. Is your DATABASE_ENGINE setting (currently, %r) spelled correctly? Available options are: %s" % \ raise ImproperlyConfigured, "Could not load database backend: %s. Is your DATABASE_ENGINE setting (currently, %r) spelled correctly? Available options are: %s" % \
(e, DATABASE_ENGINE, ", ".join(map(repr, available_backends))) (e, DATABASE_ENGINE, ", ".join(map(repr, available_backends)))
def get_introspection_module():
return __import__('django.db.backends.%s.introspection' % DATABASE_ENGINE, '', '', [''])
def get_creation_module():
return __import__('django.db.backends.%s.creation' % DATABASE_ENGINE, '', '', [''])
connection = backend.DatabaseWrapper() connection = backend.DatabaseWrapper()
DatabaseError = dbmod.DatabaseError DatabaseError = backend.DatabaseError

View File

@ -76,10 +76,10 @@ class DatabaseWrapper:
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def quote_name(self, name): def quote_name(name):
if name.startswith('[') and name.endswith(']'): if name.startswith('[') and name.endswith(']'):
return name # Quoting once is enough. return name # Quoting once is enough.
return '[%s]' % name return '[%s]' % name
dictfetchone = util.dictfetchone dictfetchone = util.dictfetchone
dictfetchmany = util.dictfetchmany dictfetchmany = util.dictfetchmany
@ -127,30 +127,3 @@ OPERATOR_MAPPING = {
'istartswith': 'LIKE %s', 'istartswith': 'LIKE %s',
'iendswith': 'LIKE %s', 'iendswith': 'LIKE %s',
} }
DATA_TYPES = {
'AutoField': 'int IDENTITY (1, 1)',
'BooleanField': 'bit',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'smalldatetime',
'DateTimeField': 'smalldatetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'int',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bit',
'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -0,0 +1,26 @@
DATA_TYPES = {
'AutoField': 'int IDENTITY (1, 1)',
'BooleanField': 'bit',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'smalldatetime',
'DateTimeField': 'smalldatetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'int',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bit',
'OneToOneField': 'int',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'int CONSTRAINT [CK_int_pos_%(column)s] CHECK ([%(column)s] > 0)',
'PositiveSmallIntegerField': 'smallint CONSTRAINT [CK_smallint_pos_%(column)s] CHECK ([%(column)s] > 0)',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -83,10 +83,10 @@ class DatabaseWrapper:
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def quote_name(self, name): def quote_name(name):
if name.startswith("`") and name.endswith("`"): if name.startswith("`") and name.endswith("`"):
return name # Quoting once is enough. return name # Quoting once is enough.
return "`%s`" % name return "`%s`" % name
dictfetchone = util.dictfetchone dictfetchone = util.dictfetchone
dictfetchmany = util.dictfetchmany dictfetchmany = util.dictfetchmany
@ -137,34 +137,3 @@ OPERATOR_MAPPING = {
'istartswith': 'LIKE %s', 'istartswith': 'LIKE %s',
'iendswith': 'LIKE %s', 'iendswith': 'LIKE %s',
} }
# This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPES = {
'AutoField': 'mediumint(9) unsigned auto_increment',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -0,0 +1,30 @@
# This dictionary maps Field objects to their associated MySQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPES = {
'AutoField': 'mediumint(9) unsigned auto_increment',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer UNSIGNED',
'PositiveSmallIntegerField': 'smallint UNSIGNED',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'longtext',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -49,10 +49,10 @@ class DatabaseWrapper:
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def quote_name(self, name): def quote_name(name):
if name.startswith('"') and name.endswith('"'): if name.startswith('"') and name.endswith('"'):
return name # Quoting once is enough. return name # Quoting once is enough.
return '"%s"' % name return '"%s"' % name
def dictfetchone(cursor): def dictfetchone(cursor):
"Returns a row from the cursor as a dict" "Returns a row from the cursor as a dict"
@ -115,34 +115,3 @@ OPERATOR_MAPPING = {
'istartswith': 'ILIKE %s', 'istartswith': 'ILIKE %s',
'iendswith': 'ILIKE %s', 'iendswith': 'ILIKE %s',
} }
# This dictionary maps Field objects to their associated PostgreSQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPES = {
'AutoField': 'serial',
'BooleanField': 'boolean',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'timestamp with time zone',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'inet',
'ManyToManyField': None,
'NullBooleanField': 'boolean',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -0,0 +1,30 @@
# This dictionary maps Field objects to their associated PostgreSQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
DATA_TYPES = {
'AutoField': 'serial',
'BooleanField': 'boolean',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'timestamp with time zone',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'inet',
'ManyToManyField': None,
'NullBooleanField': 'boolean',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer CHECK ("%(column)s" >= 0)',
'PositiveSmallIntegerField': 'smallint CHECK ("%(column)s" >= 0)',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -54,10 +54,10 @@ class DatabaseWrapper:
self.connection.close() self.connection.close()
self.connection = None self.connection = None
def quote_name(self, name): def quote_name(name):
if name.startswith('"') and name.endswith('"'): if name.startswith('"') and name.endswith('"'):
return name # Quoting once is enough. return name # Quoting once is enough.
return '"%s"' % name return '"%s"' % name
dictfetchone = util.dictfetchone dictfetchone = util.dictfetchone
dictfetchmany = util.dictfetchmany dictfetchmany = util.dictfetchmany
@ -146,33 +146,3 @@ OPERATOR_MAPPING = {
'istartswith': "LIKE %s ESCAPE '\\'", 'istartswith': "LIKE %s ESCAPE '\\'",
'iendswith': "LIKE %s ESCAPE '\\'", 'iendswith': "LIKE %s ESCAPE '\\'",
} }
# SQLite doesn't actually support most of these types, but it "does the right
# thing" given more verbose field definitions, so leave them as is so that
# schema inspection is more useful.
DATA_TYPES = {
'AutoField': 'integer',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer unsigned',
'PositiveSmallIntegerField': 'smallint unsigned',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -0,0 +1,29 @@
# SQLite doesn't actually support most of these types, but it "does the right
# thing" given more verbose field definitions, so leave them as is so that
# schema inspection is more useful.
DATA_TYPES = {
'AutoField': 'integer',
'BooleanField': 'bool',
'CharField': 'varchar(%(maxlength)s)',
'CommaSeparatedIntegerField': 'varchar(%(maxlength)s)',
'DateField': 'date',
'DateTimeField': 'datetime',
'FileField': 'varchar(100)',
'FilePathField': 'varchar(100)',
'FloatField': 'numeric(%(max_digits)s, %(decimal_places)s)',
'ImageField': 'varchar(100)',
'IntegerField': 'integer',
'IPAddressField': 'char(15)',
'ManyToManyField': None,
'NullBooleanField': 'bool',
'OneToOneField': 'integer',
'PhoneNumberField': 'varchar(20)',
'PositiveIntegerField': 'integer unsigned',
'PositiveSmallIntegerField': 'smallint unsigned',
'SlugField': 'varchar(50)',
'SmallIntegerField': 'smallint',
'TextField': 'text',
'TimeField': 'time',
'URLField': 'varchar(200)',
'USStateField': 'varchar(2)',
}

View File

@ -1,7 +1,7 @@
from django.conf import settings from django.conf import settings
from django.core import formfields, validators from django.core import formfields, validators
from django.core import db
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import backend, connection
from django.db.models.fields import * from django.db.models.fields import *
from django.utils.functional import curry from django.utils.functional import curry
from django.utils.text import capfirst from django.utils.text import capfirst
@ -58,15 +58,15 @@ def orderfield2column(f, opts):
def orderlist2sql(order_list, opts, prefix=''): def orderlist2sql(order_list, opts, prefix=''):
if prefix.endswith('.'): if prefix.endswith('.'):
prefix = db.db.quote_name(prefix[:-1]) + '.' prefix = backend.quote_name(prefix[:-1]) + '.'
output = [] output = []
for f in handle_legacy_orderlist(order_list): for f in handle_legacy_orderlist(order_list):
if f.startswith('-'): if f.startswith('-'):
output.append('%s%s DESC' % (prefix, db.db.quote_name(orderfield2column(f[1:], opts)))) output.append('%s%s DESC' % (prefix, backend.quote_name(orderfield2column(f[1:], opts))))
elif f == '?': elif f == '?':
output.append(db.get_random_function_sql()) output.append(backend.get_random_function_sql())
else: else:
output.append('%s%s ASC' % (prefix, db.db.quote_name(orderfield2column(f, opts)))) output.append('%s%s ASC' % (prefix, backend.quote_name(orderfield2column(f, opts))))
return ', '.join(output) return ', '.join(output)
def get_module(app_label, module_name): def get_module(app_label, module_name):
@ -536,24 +536,6 @@ class Options:
self._field_types[field_type] = False self._field_types[field_type] = False
return self._field_types[field_type] return self._field_types[field_type]
def _reassign_globals(function_dict, extra_globals, namespace):
new_functions = {}
for k, v in function_dict.items():
# Get the code object.
code = v.func_code
# Recreate the function, but give it access to extra_globals and the
# given namespace's globals, too.
new_globals = {'__builtins__': __builtins__, 'db': db.db, 'datetime': datetime}
new_globals.update(extra_globals.__dict__)
func = types.FunctionType(code, globals=new_globals, name=k, argdefs=v.func_defaults)
func.__dict__.update(v.__dict__)
setattr(namespace, k, func)
# For all of the custom functions that have been added so far, give
# them access to the new function we've just created.
for new_k, new_v in new_functions.items():
new_v.func_globals[k] = func
new_functions[k] = func
# Calculate the module_name using a poor-man's pluralization. # Calculate the module_name using a poor-man's pluralization.
get_module_name = lambda class_name: class_name.lower() + 's' get_module_name = lambda class_name: class_name.lower() + 's'
@ -582,12 +564,12 @@ class Manager(object):
if ' ' in word: if ' ' in word:
return word return word
else: else:
return db.db.quote_name(word) return backend.quote_name(word)
opts = self.klass._meta opts = self.klass._meta
# Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z. # Construct the fundamental parts of the query: SELECT X FROM Y WHERE Z.
select = ["%s.%s" % (db.db.quote_name(opts.db_table), db.db.quote_name(f.column)) for f in opts.fields] select = ["%s.%s" % (backend.quote_name(opts.db_table), backend.quote_name(f.column)) for f in opts.fields]
tables = [opts.db_table] + (kwargs.get('tables') and kwargs['tables'][:] or []) tables = [opts.db_table] + (kwargs.get('tables') and kwargs['tables'][:] or [])
tables = [quote_only_if_word(t) for t in tables] tables = [quote_only_if_word(t) for t in tables]
where = kwargs.get('where') and kwargs['where'][:] or [] where = kwargs.get('where') and kwargs['where'][:] or []
@ -608,13 +590,13 @@ class Manager(object):
# Add any additional SELECTs passed in via kwargs. # Add any additional SELECTs passed in via kwargs.
if kwargs.get('select'): if kwargs.get('select'):
select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), db.db.quote_name(s[0])) for s in kwargs['select']]) select.extend(['(%s) AS %s' % (quote_only_if_word(s[1]), backend.quote_name(s[0])) for s in kwargs['select']])
# ORDER BY clause # ORDER BY clause
order_by = [] order_by = []
for f in handle_legacy_orderlist(kwargs.get('order_by', opts.ordering)): for f in handle_legacy_orderlist(kwargs.get('order_by', opts.ordering)):
if f == '?': # Special case. if f == '?': # Special case.
order_by.append(db.get_random_function_sql()) order_by.append(backend.get_random_function_sql())
else: else:
if f.startswith('-'): if f.startswith('-'):
col_name = f[1:] col_name = f[1:]
@ -624,20 +606,20 @@ class Manager(object):
order = "ASC" order = "ASC"
if "." in col_name: if "." in col_name:
table_prefix, col_name = col_name.split('.', 1) table_prefix, col_name = col_name.split('.', 1)
table_prefix = db.db.quote_name(table_prefix) + '.' table_prefix = backend.quote_name(table_prefix) + '.'
else: else:
# Use the database table as a column prefix if it wasn't given, # Use the database table as a column prefix if it wasn't given,
# and if the requested column isn't a custom SELECT. # and if the requested column isn't a custom SELECT.
if "." not in col_name and col_name not in [k[0] for k in kwargs.get('select', [])]: if "." not in col_name and col_name not in [k[0] for k in kwargs.get('select', [])]:
table_prefix = db.db.quote_name(opts.db_table) + '.' table_prefix = backend.quote_name(opts.db_table) + '.'
else: else:
table_prefix = '' table_prefix = ''
order_by.append('%s%s %s' % (table_prefix, db.db.quote_name(orderfield2column(col_name, opts)), order)) order_by.append('%s%s %s' % (table_prefix, backend.quote_name(orderfield2column(col_name, opts)), order))
order_by = ", ".join(order_by) order_by = ", ".join(order_by)
# LIMIT and OFFSET clauses # LIMIT and OFFSET clauses
if kwargs.get('limit') is not None: if kwargs.get('limit') is not None:
limit_sql = " %s " % db.get_limit_offset_sql(kwargs['limit'], kwargs.get('offset')) limit_sql = " %s " % backend.get_limit_offset_sql(kwargs['limit'], kwargs.get('offset'))
else: else:
assert kwargs.get('offset') is None, "'offset' is not allowed without 'limit'" assert kwargs.get('offset') is None, "'offset' is not allowed without 'limit'"
limit_sql = "" limit_sql = ""
@ -649,7 +631,7 @@ class Manager(object):
# undefined, so we convert it to a list of tuples internally. # undefined, so we convert it to a list of tuples internally.
kwargs['select'] = kwargs.get('select', {}).items() kwargs['select'] = kwargs.get('select', {}).items()
cursor = db.db.cursor() cursor = connection.cursor()
select, sql, params = self._get_sql_clause(**kwargs) select, sql, params = self._get_sql_clause(**kwargs)
cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params)
fill_cache = kwargs.get('select_related') fill_cache = kwargs.get('select_related')
@ -676,7 +658,7 @@ class Manager(object):
kwargs['limit'] = None kwargs['limit'] = None
kwargs['select_related'] = False kwargs['select_related'] = False
_, sql, params = self._get_sql_clause(**kwargs) _, sql, params = self._get_sql_clause(**kwargs)
cursor = db.db.cursor() cursor = connection.cursor()
cursor.execute("SELECT COUNT(*)" + sql, params) cursor.execute("SELECT COUNT(*)" + sql, params)
return cursor.fetchone()[0] return cursor.fetchone()[0]
@ -690,7 +672,7 @@ class Manager(object):
def get_in_bulk(self, *args, **kwargs): def get_in_bulk(self, *args, **kwargs):
id_list = args and args[0] or kwargs['id_list'] id_list = args and args[0] or kwargs['id_list']
assert id_list != [], "get_in_bulk() cannot be passed an empty list." assert id_list != [], "get_in_bulk() cannot be passed an empty list."
kwargs['where'] = ["%s.%s IN (%s)" % (db.db.quote_name(self.klass._meta.db_table), db.db.quote_name(self.klass._meta.pk.column), ",".join(['%s'] * len(id_list)))] kwargs['where'] = ["%s.%s IN (%s)" % (backend.quote_name(self.klass._meta.db_table), backend.quote_name(self.klass._meta.pk.column), ",".join(['%s'] * len(id_list)))]
kwargs['params'] = id_list kwargs['params'] = id_list
obj_list = self.get_list(**kwargs) obj_list = self.get_list(**kwargs)
return dict([(getattr(o, self.klass._meta.pk.attname), o) for o in obj_list]) return dict([(getattr(o, self.klass._meta.pk.attname), o) for o in obj_list])
@ -706,9 +688,9 @@ class Manager(object):
except KeyError: # Default to all fields. except KeyError: # Default to all fields.
fields = [f.column for f in self.klass._meta.fields] fields = [f.column for f in self.klass._meta.fields]
cursor = db.db.cursor() cursor = connection.cursor()
_, sql, params = self._get_sql_clause(**kwargs) _, sql, params = self._get_sql_clause(**kwargs)
select = ['%s.%s' % (db.db.quote_name(self.klass._meta.db_table), db.db.quote_name(f)) for f in fields] select = ['%s.%s' % (backend.quote_name(self.klass._meta.db_table), backend.quote_name(f)) for f in fields]
cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params)
while 1: while 1:
rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE)
@ -726,7 +708,7 @@ class Manager(object):
return self.get_object(**kwargs) return self.get_object(**kwargs)
def __get_date_list(self, field, *args, **kwargs): def __get_date_list(self, field, *args, **kwargs):
from django.core.db.typecasts import typecast_timestamp from django.db.backends.util import typecast_timestamp
kind = args and args[0] or kwargs['kind'] kind = args and args[0] or kwargs['kind']
assert kind in ("month", "year", "day"), "'kind' must be one of 'year', 'month' or 'day'." assert kind in ("month", "year", "day"), "'kind' must be one of 'year', 'month' or 'day'."
order = 'ASC' order = 'ASC'
@ -737,12 +719,12 @@ class Manager(object):
kwargs['order_by'] = () # Clear this because it'll mess things up otherwise. kwargs['order_by'] = () # Clear this because it'll mess things up otherwise.
if field.null: if field.null:
kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % \ kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % \
(db.db.quote_name(self.klass._meta.db_table), db.db.quote_name(field.column))) (backend.quote_name(self.klass._meta.db_table), backend.quote_name(field.column)))
select, sql, params = self._get_sql_clause(**kwargs) select, sql, params = self._get_sql_clause(**kwargs)
sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \
(db.get_date_trunc_sql(kind, '%s.%s' % (db.db.quote_name(self.klass._meta.db_table), (backend.get_date_trunc_sql(kind, '%s.%s' % (backend.quote_name(self.klass._meta.db_table),
db.db.quote_name(field.column))), sql, order) backend.quote_name(field.column))), sql, order)
cursor = db.db.cursor() cursor = connection.cursor()
cursor.execute(sql, params) cursor.execute(sql, params)
# We have to manually run typecast_timestamp(str()) on the results, because # We have to manually run typecast_timestamp(str()) on the results, because
# MySQL doesn't automatically cast the result of date functions as datetime # MySQL doesn't automatically cast the result of date functions as datetime
@ -969,7 +951,7 @@ class Model(object):
self._pre_save() self._pre_save()
non_pks = [f for f in self._meta.fields if not f.primary_key] non_pks = [f for f in self._meta.fields if not f.primary_key]
cursor = db.db.cursor() cursor = connection.cursor()
# First, try an UPDATE. If that doesn't update anything, do an INSERT. # First, try an UPDATE. If that doesn't update anything, do an INSERT.
pk_val = getattr(self, self._meta.pk.attname) pk_val = getattr(self, self._meta.pk.attname)
@ -978,19 +960,19 @@ class Model(object):
if pk_set: if pk_set:
# Determine whether a record with the primary key already exists. # Determine whether a record with the primary key already exists.
cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \ cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \
(db.db.quote_name(self._meta.db_table), db.db.quote_name(self._meta.pk.column)), [pk_val]) (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val])
# If it does already exist, do an UPDATE. # If it does already exist, do an UPDATE.
if cursor.fetchone(): if cursor.fetchone():
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks] db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), False)) for f in non_pks]
cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \ cursor.execute("UPDATE %s SET %s WHERE %s=%%s" % \
(db.db.quote_name(self._meta.db_table), (backend.quote_name(self._meta.db_table),
','.join(['%s=%%s' % db.db.quote_name(f.column) for f in non_pks]), ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]),
db.db.quote_name(self._meta.pk.attname)), backend.quote_name(self._meta.pk.attname)),
db_values + [pk_val]) db_values + [pk_val])
else: else:
record_exists = False record_exists = False
if not pk_set or not record_exists: if not pk_set or not record_exists:
field_names = [db.db.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)] field_names = [backend.quote_name(f.column) for f in self._meta.fields if not isinstance(f, AutoField)]
db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in self._meta.fields if not isinstance(f, AutoField)] db_values = [f.get_db_prep_save(f.pre_save(getattr(self, f.attname), True)) for f in self._meta.fields if not isinstance(f, AutoField)]
# If the PK has been manually set, respect that. # If the PK has been manually set, respect that.
if pk_set: if pk_set:
@ -998,17 +980,17 @@ class Model(object):
db_values += [f.get_db_prep_save(f.pre_save(getattr(self, f.column), True)) for f in self._meta.fields if isinstance(f, AutoField)] db_values += [f.get_db_prep_save(f.pre_save(getattr(self, f.column), True)) for f in self._meta.fields if isinstance(f, AutoField)]
placeholders = ['%s'] * len(field_names) placeholders = ['%s'] * len(field_names)
if self._meta.order_with_respect_to: if self._meta.order_with_respect_to:
field_names.append(db.db.quote_name('_order')) field_names.append(backend.quote_name('_order'))
# TODO: This assumes the database supports subqueries. # TODO: This assumes the database supports subqueries.
placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \ placeholders.append('(SELECT COUNT(*) FROM %s WHERE %s = %%s)' % \
(db.db.quote_name(self._meta.db_table), db.db.quote_name(self._meta.order_with_respect_to.column))) (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.order_with_respect_to.column)))
db_values.append(getattr(self, self._meta.order_with_respect_to.attname)) db_values.append(getattr(self, self._meta.order_with_respect_to.attname))
cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \ cursor.execute("INSERT INTO %s (%s) VALUES (%s)" % \
(db.db.quote_name(self._meta.db_table), ','.join(field_names), (backend.quote_name(self._meta.db_table), ','.join(field_names),
','.join(placeholders)), db_values) ','.join(placeholders)), db_values)
if self._meta.has_auto_field and not pk_set: if self._meta.has_auto_field and not pk_set:
setattr(self, self._meta.pk.attname, db.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column)) setattr(self, self._meta.pk.attname, backend.get_last_insert_id(cursor, self._meta.db_table, self._meta.pk.column))
db.db.commit() connection.commit()
# Run any post-save hooks. # Run any post-save hooks.
if hasattr(self, '_post_save'): if hasattr(self, '_post_save'):
@ -1023,7 +1005,7 @@ class Model(object):
if hasattr(self, '_pre_delete'): if hasattr(self, '_pre_delete'):
self._pre_delete() self._pre_delete()
cursor = db.db.cursor() cursor = connection.cursor()
for related in self._meta.get_all_related_objects(): for related in self._meta.get_all_related_objects():
rel_opts_name = related.get_method_name_part() rel_opts_name = related.get_method_name_part()
if isinstance(related.field.rel, OneToOne): if isinstance(related.field.rel, OneToOne):
@ -1038,17 +1020,17 @@ class Model(object):
sub_obj.delete() sub_obj.delete()
for related in self._meta.get_all_related_many_to_many_objects(): for related in self._meta.get_all_related_many_to_many_objects():
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \ cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(db.db.quote_name(related.field.get_m2m_db_table(related.opts)), (backend.quote_name(related.field.get_m2m_db_table(related.opts)),
db.db.quote_name(self._meta.object_name.lower() + '_id')), [getattr(self, self._meta.pk.attname)]) backend.quote_name(self._meta.object_name.lower() + '_id')), [getattr(self, self._meta.pk.attname)])
for f in self._meta.many_to_many: for f in self._meta.many_to_many:
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \ cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(db.db.quote_name(f.get_m2m_db_table(self._meta)), (backend.quote_name(f.get_m2m_db_table(self._meta)),
db.db.quote_name(self._meta.object_name.lower() + '_id')), backend.quote_name(self._meta.object_name.lower() + '_id')),
[getattr(self, self._meta.pk.attname)]) [getattr(self, self._meta.pk.attname)])
cursor.execute("DELETE FROM %s WHERE %s=%%s" % \ cursor.execute("DELETE FROM %s WHERE %s=%%s" % \
(db.db.quote_name(self._meta.db_table), db.db.quote_name(self._meta.pk.column)), (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)),
[getattr(self, self._meta.pk.attname)]) [getattr(self, self._meta.pk.attname)])
db.db.commit() connection.commit()
setattr(self, self._meta.pk.attname, None) setattr(self, self._meta.pk.attname, None)
for f in self._meta.fields: for f in self._meta.fields:
if isinstance(f, FileField) and getattr(self, f.attname): if isinstance(f, FileField) and getattr(self, f.attname):
@ -1071,8 +1053,8 @@ class Model(object):
def __get_next_or_previous_by_FIELD(self, field, is_next, **kwargs): def __get_next_or_previous_by_FIELD(self, field, is_next, **kwargs):
op = is_next and '>' or '<' op = is_next and '>' or '<'
kwargs.setdefault('where', []).append('(%s %s %%s OR (%s = %%s AND %s.%s %s %%s))' % \ kwargs.setdefault('where', []).append('(%s %s %%s OR (%s = %%s AND %s.%s %s %%s))' % \
(db.db.quote_name(field.column), op, db.db.quote_name(field.column), (backend.quote_name(field.column), op, backend.quote_name(field.column),
db.db.quote_name(self._meta.db_table), db.db.quote_name(self._meta.pk.column), op)) backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column), op))
param = str(getattr(self, field.attname)) param = str(getattr(self, field.attname))
kwargs.setdefault('params', []).extend([param, param, getattr(self, self._meta.pk.attname)]) kwargs.setdefault('params', []).extend([param, param, getattr(self, self._meta.pk.attname)])
kwargs['order_by'] = [(not is_next and '-' or '') + field.name, (not is_next and '-' or '') + self._meta.pk.name] kwargs['order_by'] = [(not is_next and '-' or '') + field.name, (not is_next and '-' or '') + self._meta.pk.name]
@ -1086,9 +1068,9 @@ class Model(object):
order_field = self.order_with_respect_to order_field = self.order_with_respect_to
obj = self.objects.get_object(order_by=('_order',), obj = self.objects.get_object(order_by=('_order',),
where=['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \ where=['%s %s (SELECT %s FROM %s WHERE %s=%%s)' % \
(db.db.quote_name('_order'), op, db.db.quote_name('_order'), (backend.quote_name('_order'), op, backend.quote_name('_order'),
db.db.quote_name(opts.db_table), db.db.quote_name(opts.pk.column)), backend.quote_name(opts.db_table), backend.quote_name(opts.pk.column)),
'%s=%%s' % db.db.quote_name(order_field.column)], '%s=%%s' % backend.quote_name(order_field.column)],
limit=1, limit=1,
params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)]) params=[getattr(self, opts.pk.attname), getattr(self, order_field.attname)])
setattr(self, cachename, obj) setattr(self, cachename, obj)
@ -1180,13 +1162,13 @@ class Model(object):
if not hasattr(self, cache_var): if not hasattr(self, cache_var):
rel_opts = field_with_rel.rel.to._meta rel_opts = field_with_rel.rel.to._meta
sql = "SELECT %s FROM %s a, %s b WHERE a.%s = b.%s AND b.%s = %%s %s" % \ sql = "SELECT %s FROM %s a, %s b WHERE a.%s = b.%s AND b.%s = %%s %s" % \
(','.join(['a.%s' % db.db.quote_name(f.column) for f in rel_opts.fields]), (','.join(['a.%s' % backend.quote_name(f.column) for f in rel_opts.fields]),
db.db.quote_name(rel_opts.db_table), backend.quote_name(rel_opts.db_table),
db.db.quote_name(field_with_rel.get_m2m_db_table(self._meta)), backend.quote_name(field_with_rel.get_m2m_db_table(self._meta)),
db.db.quote_name(rel_opts.pk.column), backend.quote_name(rel_opts.pk.column),
db.db.quote_name(rel_opts.object_name.lower() + '_id'), backend.quote_name(rel_opts.object_name.lower() + '_id'),
db.db.quote_name(self._meta.object_name.lower() + '_id'), rel_opts.get_order_sql('a')) backend.quote_name(self._meta.object_name.lower() + '_id'), rel_opts.get_order_sql('a'))
cursor = db.db.cursor() cursor = connection.cursor()
cursor.execute(sql, [getattr(self, self._meta.pk.attname)]) cursor.execute(sql, [getattr(self, self._meta.pk.attname)])
setattr(self, cache_var, [field_with_rel.rel.to(*row) for row in cursor.fetchall()]) setattr(self, cache_var, [field_with_rel.rel.to(*row) for row in cursor.fetchall()])
return getattr(self, cache_var) return getattr(self, cache_var)
@ -1205,21 +1187,21 @@ class Model(object):
return False # No change return False # No change
rel = field_with_rel.rel.to._meta rel = field_with_rel.rel.to._meta
m2m_table = field_with_rel.get_m2m_db_table(self._meta) m2m_table = field_with_rel.get_m2m_db_table(self._meta)
cursor = db.db.cursor() cursor = connection.cursor()
this_id = getattr(self, self._meta.pk.attname) this_id = getattr(self, self._meta.pk.attname)
if ids_to_delete: if ids_to_delete:
sql = "DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \ sql = "DELETE FROM %s WHERE %s = %%s AND %s IN (%s)" % \
(db.db.quote_name(m2m_table), (backend.quote_name(m2m_table),
db.db.quote_name(self._meta.object_name.lower() + '_id'), backend.quote_name(self._meta.object_name.lower() + '_id'),
db.db.quote_name(rel.object_name.lower() + '_id'), ','.join(map(str, ids_to_delete))) backend.quote_name(rel.object_name.lower() + '_id'), ','.join(map(str, ids_to_delete)))
cursor.execute(sql, [this_id]) cursor.execute(sql, [this_id])
if ids_to_add: if ids_to_add:
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(db.db.quote_name(m2m_table), (backend.quote_name(m2m_table),
db.db.quote_name(self._meta.object_name.lower() + '_id'), backend.quote_name(self._meta.object_name.lower() + '_id'),
db.db.quote_name(rel.object_name.lower() + '_id')) backend.quote_name(rel.object_name.lower() + '_id'))
cursor.executemany(sql, [(this_id, i) for i in ids_to_add]) cursor.executemany(sql, [(this_id, i) for i in ids_to_add])
db.db.commit() connection.commit()
try: try:
delattr(self, '_%s_cache' % field_with_rel.name) # clear cache, if it exists delattr(self, '_%s_cache' % field_with_rel.name) # clear cache, if it exists
except AttributeError: except AttributeError:
@ -1265,38 +1247,38 @@ def method_set_related_many_to_many(rel_opts, rel_field, self, id_list):
rel = rel_field.rel.to rel = rel_field.rel.to
m2m_table = rel_field.get_m2m_db_table(rel_opts) m2m_table = rel_field.get_m2m_db_table(rel_opts)
this_id = getattr(self, self._meta.pk.attname) this_id = getattr(self, self._meta.pk.attname)
cursor = db.db.cursor() cursor = connection.cursor()
cursor.execute("DELETE FROM %s WHERE %s = %%s" % \ cursor.execute("DELETE FROM %s WHERE %s = %%s" % \
(db.db.quote_name(m2m_table), (backend.quote_name(m2m_table),
db.db.quote_name(rel.object_name.lower() + '_id')), [this_id]) backend.quote_name(rel.object_name.lower() + '_id')), [this_id])
sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \ sql = "INSERT INTO %s (%s, %s) VALUES (%%s, %%s)" % \
(db.db.quote_name(m2m_table), (backend.quote_name(m2m_table),
db.db.quote_name(rel.object_name.lower() + '_id'), backend.quote_name(rel.object_name.lower() + '_id'),
db.db.quote_name(rel_opts.object_name.lower() + '_id')) backend.quote_name(rel_opts.object_name.lower() + '_id'))
cursor.executemany(sql, [(this_id, i) for i in id_list]) cursor.executemany(sql, [(this_id, i) for i in id_list])
db.db.commit() connection.commit()
# ORDERING METHODS ######################### # ORDERING METHODS #########################
def method_set_order(ordered_obj, self, id_list): def method_set_order(ordered_obj, self, id_list):
cursor = db.db.cursor() cursor = connection.cursor()
# Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s" # Example: "UPDATE poll_choices SET _order = %s WHERE poll_id = %s AND id = %s"
sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \ sql = "UPDATE %s SET %s = %%s WHERE %s = %%s AND %s = %%s" % \
(db.db.quote_name(ordered_obj.db_table), db.db.quote_name('_order'), (backend.quote_name(ordered_obj.db_table), backend.quote_name('_order'),
db.db.quote_name(ordered_obj.order_with_respect_to.column), backend.quote_name(ordered_obj.order_with_respect_to.column),
db.db.quote_name(ordered_obj.pk.column)) backend.quote_name(ordered_obj.pk.column))
rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name) rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name)
cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)]) cursor.executemany(sql, [(i, rel_val, j) for i, j in enumerate(id_list)])
db.db.commit() connection.commit()
def method_get_order(ordered_obj, self): def method_get_order(ordered_obj, self):
cursor = db.db.cursor() cursor = connection.cursor()
# Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order" # Example: "SELECT id FROM poll_choices WHERE poll_id = %s ORDER BY _order"
sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY %s" % \ sql = "SELECT %s FROM %s WHERE %s = %%s ORDER BY %s" % \
(db.db.quote_name(ordered_obj.pk.column), (backend.quote_name(ordered_obj.pk.column),
db.db.quote_name(ordered_obj.db_table), backend.quote_name(ordered_obj.db_table),
db.db.quote_name(ordered_obj.order_with_respect_to.column), backend.quote_name(ordered_obj.order_with_respect_to.column),
db.db.quote_name('_order')) backend.quote_name('_order'))
rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name) rel_val = getattr(self, ordered_obj.order_with_respect_to.rel.field_name)
cursor.execute(sql, [rel_val]) cursor.execute(sql, [rel_val])
return [r[0] for r in cursor.fetchall()] return [r[0] for r in cursor.fetchall()]
@ -1310,10 +1292,10 @@ def get_absolute_url(opts, func, self):
def _get_where_clause(lookup_type, table_prefix, field_name, value): def _get_where_clause(lookup_type, table_prefix, field_name, value):
if table_prefix.endswith('.'): if table_prefix.endswith('.'):
table_prefix = db.db.quote_name(table_prefix[:-1])+'.' table_prefix = backend.quote_name(table_prefix[:-1])+'.'
field_name = db.db.quote_name(field_name) field_name = backend.quote_name(field_name)
try: try:
return '%s%s %s' % (table_prefix, field_name, (db.OPERATOR_MAPPING[lookup_type] % '%s')) return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s'))
except KeyError: except KeyError:
pass pass
if lookup_type == 'in': if lookup_type == 'in':
@ -1321,7 +1303,7 @@ def _get_where_clause(lookup_type, table_prefix, field_name, value):
elif lookup_type in ('range', 'year'): elif lookup_type in ('range', 'year'):
return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name) return '%s%s BETWEEN %%s AND %%s' % (table_prefix, field_name)
elif lookup_type in ('month', 'day'): elif lookup_type in ('month', 'day'):
return "%s = %%s" % db.get_date_extract_sql(lookup_type, table_prefix + field_name) return "%s = %%s" % backend.get_date_extract_sql(lookup_type, table_prefix + field_name)
elif lookup_type == 'isnull': elif lookup_type == 'isnull':
return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or '')) return "%s%s IS %sNULL" % (table_prefix, field_name, (not value and 'NOT ' or ''))
raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type) raise TypeError, "Got invalid lookup_type: %s" % repr(lookup_type)
@ -1345,16 +1327,16 @@ def _fill_table_cache(opts, select, tables, where, old_prefix, cache_tables_seen
if f.rel and not f.null: if f.rel and not f.null:
db_table = f.rel.to._meta.db_table db_table = f.rel.to._meta.db_table
if db_table not in cache_tables_seen: if db_table not in cache_tables_seen:
tables.append(db.db.quote_name(db_table)) tables.append(backend.quote_name(db_table))
else: # The table was already seen, so give it a table alias. else: # The table was already seen, so give it a table alias.
new_prefix = '%s%s' % (db_table, len(cache_tables_seen)) new_prefix = '%s%s' % (db_table, len(cache_tables_seen))
tables.append('%s %s' % (db.db.quote_name(db_table), db.db.quote_name(new_prefix))) tables.append('%s %s' % (backend.quote_name(db_table), backend.quote_name(new_prefix)))
db_table = new_prefix db_table = new_prefix
cache_tables_seen.append(db_table) cache_tables_seen.append(db_table)
where.append('%s.%s = %s.%s' % \ where.append('%s.%s = %s.%s' % \
(db.db.quote_name(old_prefix), db.db.quote_name(f.column), (backend.quote_name(old_prefix), backend.quote_name(f.column),
db.db.quote_name(db_table), db.db.quote_name(f.rel.get_related_field().column))) backend.quote_name(db_table), backend.quote_name(f.rel.get_related_field().column)))
select.extend(['%s.%s' % (db.db.quote_name(db_table), db.db.quote_name(f2.column)) for f2 in f.rel.to._meta.fields]) select.extend(['%s.%s' % (backend.quote_name(db_table), backend.quote_name(f2.column)) for f2 in f.rel.to._meta.fields])
_fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) _fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen)
def _throw_bad_kwarg_error(kwarg): def _throw_bad_kwarg_error(kwarg):
@ -1420,15 +1402,15 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
# Try many-to-many relationships first... # Try many-to-many relationships first...
for f in current_opts.many_to_many: for f in current_opts.many_to_many:
if f.name == current: if f.name == current:
rel_table_alias = db.db.quote_name('t%s' % table_count) rel_table_alias = backend.quote_name('t%s' % table_count)
table_count += 1 table_count += 1
tables.append('%s %s' % \ tables.append('%s %s' % \
(db.db.quote_name(f.get_m2m_db_table(current_opts)), rel_table_alias)) (backend.quote_name(f.get_m2m_db_table(current_opts)), rel_table_alias))
join_where.append('%s.%s = %s.%s' % \ join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(current_table_alias), (backend.quote_name(current_table_alias),
db.db.quote_name(current_opts.pk.column), backend.quote_name(current_opts.pk.column),
rel_table_alias, rel_table_alias,
db.db.quote_name(current_opts.object_name.lower() + '_id'))) backend.quote_name(current_opts.object_name.lower() + '_id')))
# Optimization: In the case of primary-key lookups, we # Optimization: In the case of primary-key lookups, we
# don't have to do an extra join. # don't have to do an extra join.
if lookup_list and lookup_list[0] == f.rel.to._meta.pk.name and lookup_type == 'exact': if lookup_list and lookup_list[0] == f.rel.to._meta.pk.name and lookup_type == 'exact':
@ -1439,13 +1421,13 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
param_required = False param_required = False
else: else:
new_table_alias = 't%s' % table_count new_table_alias = 't%s' % table_count
tables.append('%s %s' % (db.db.quote_name(f.rel.to._meta.db_table), tables.append('%s %s' % (backend.quote_name(f.rel.to._meta.db_table),
db.db.quote_name(new_table_alias))) backend.quote_name(new_table_alias)))
join_where.append('%s.%s = %s.%s' % \ join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(rel_table_alias), (backend.quote_name(rel_table_alias),
db.db.quote_name(f.rel.to._meta.object_name.lower() + '_id'), backend.quote_name(f.rel.to._meta.object_name.lower() + '_id'),
db.db.quote_name(new_table_alias), backend.quote_name(new_table_alias),
db.db.quote_name(f.rel.to._meta.pk.column))) backend.quote_name(f.rel.to._meta.pk.column)))
current_table_alias = new_table_alias current_table_alias = new_table_alias
param_required = True param_required = True
current_opts = f.rel.to._meta current_opts = f.rel.to._meta
@ -1469,10 +1451,10 @@ def _parse_lookup(kwarg_items, opts, table_count=0):
else: else:
new_table_alias = 't%s' % table_count new_table_alias = 't%s' % table_count
tables.append('%s %s' % \ tables.append('%s %s' % \
(db.db.quote_name(f.rel.to._meta.db_table), db.db.quote_name(new_table_alias))) (backend.quote_name(f.rel.to._meta.db_table), backend.quote_name(new_table_alias)))
join_where.append('%s.%s = %s.%s' % \ join_where.append('%s.%s = %s.%s' % \
(db.db.quote_name(current_table_alias), db.db.quote_name(f.column), (backend.quote_name(current_table_alias), backend.quote_name(f.column),
db.db.quote_name(new_table_alias), db.db.quote_name(f.rel.to._meta.pk.column))) backend.quote_name(new_table_alias), backend.quote_name(f.rel.to._meta.pk.column)))
current_table_alias = new_table_alias current_table_alias = new_table_alias
param_required = True param_required = True
current_opts = f.rel.to._meta current_opts = f.rel.to._meta

View File

@ -24,8 +24,8 @@ class Article(models.Model):
Verbose version of get_articles_from_same_day_1, which does a custom Verbose version of get_articles_from_same_day_1, which does a custom
database query for the sake of demonstration. database query for the sake of demonstration.
""" """
from django.core.db import db from django.db import connection
cursor = db.cursor() cursor = connection.cursor()
cursor.execute(""" cursor.execute("""
SELECT id, headline, pub_date SELECT id, headline, pub_date
FROM custom_methods_articles FROM custom_methods_articles

View File

@ -1,6 +1,6 @@
# Unit tests for django.core.db.typecasts # Unit tests for typecast functions in django.db.backends.util
from django.core.db import typecasts from django.db.backends import util as typecasts
import datetime import datetime
TEST_CASES = { TEST_CASES = {

View File

@ -68,7 +68,7 @@ class TestRunner:
# Manually set INSTALLED_APPS to point to the test models. # Manually set INSTALLED_APPS to point to the test models.
settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()] settings.INSTALLED_APPS = [MODEL_TESTS_DIR_NAME + '.' + a for a in get_test_models()]
from django.core.db import db from django.db import connection
from django.core import management from django.core import management
# Determine which models we're going to test. # Determine which models we're going to test.
@ -93,9 +93,9 @@ class TestRunner:
# Create the test database and connect to it. We need autocommit() # Create the test database and connect to it. We need autocommit()
# because PostgreSQL doesn't allow CREATE DATABASE statements # because PostgreSQL doesn't allow CREATE DATABASE statements
# within transactions. # within transactions.
cursor = db.cursor() cursor = connection.cursor()
try: try:
db.connection.autocommit(1) connection.connection.autocommit(1)
except AttributeError: except AttributeError:
pass pass
self.output(1, "Creating test database") self.output(1, "Creating test database")
@ -110,12 +110,12 @@ class TestRunner:
else: else:
print "Tests cancelled." print "Tests cancelled."
return return
db.close() connection.close()
old_database_name = settings.DATABASE_NAME old_database_name = settings.DATABASE_NAME
settings.DATABASE_NAME = TEST_DATABASE_NAME settings.DATABASE_NAME = TEST_DATABASE_NAME
# Initialize the test database. # Initialize the test database.
cursor = db.cursor() cursor = connection.cursor()
self.output(1, "Initializing test database") self.output(1, "Initializing test database")
management.init() management.init()
@ -145,7 +145,7 @@ class TestRunner:
finally: finally:
# Rollback, in case of database errors. Otherwise they'd have # Rollback, in case of database errors. Otherwise they'd have
# side effects on other tests. # side effects on other tests.
db.rollback() connection.rollback()
if not self.which_tests: if not self.which_tests:
# Run the non-model tests in the other tests dir # Run the non-model tests in the other tests dir
@ -178,12 +178,12 @@ class TestRunner:
# to do so, because it's not allowed to delete a database while being # to do so, because it's not allowed to delete a database while being
# connected to it. # connected to it.
if settings.DATABASE_ENGINE != "sqlite3": if settings.DATABASE_ENGINE != "sqlite3":
db.close() connection.close()
settings.DATABASE_NAME = old_database_name settings.DATABASE_NAME = old_database_name
cursor = db.cursor() cursor = connection.cursor()
self.output(1, "Deleting test database") self.output(1, "Deleting test database")
try: try:
db.connection.autocommit(1) connection.connection.autocommit(1)
except AttributeError: except AttributeError:
pass pass
else: else: