2013-01-06 06:43:01 +08:00
|
|
|
from django.conf import settings
|
2013-10-19 06:49:24 +08:00
|
|
|
from django.core.cache import caches
|
2011-11-20 03:56:31 +08:00
|
|
|
from django.core.cache.backends.db import BaseDatabaseCache
|
2013-01-06 06:43:01 +08:00
|
|
|
from django.core.management.base import BaseCommand, CommandError
|
2015-01-28 20:35:27 +08:00
|
|
|
from django.db import (
|
|
|
|
DEFAULT_DB_ALIAS, connections, models, router, transaction,
|
|
|
|
)
|
2012-01-09 04:00:30 +08:00
|
|
|
from django.db.utils import DatabaseError
|
2012-07-21 16:00:10 +08:00
|
|
|
from django.utils.encoding import force_text
|
2012-06-08 00:08:47 +08:00
|
|
|
|
2007-08-16 14:06:55 +08:00
|
|
|
|
2013-01-06 06:43:01 +08:00
|
|
|
class Command(BaseCommand):
|
|
|
|
help = "Creates the tables needed to use the SQL cache backend."
|
2007-08-16 14:06:55 +08:00
|
|
|
|
2014-01-20 10:45:21 +08:00
|
|
|
requires_system_checks = False
|
2007-08-16 14:06:55 +08:00
|
|
|
|
2014-06-07 04:39:33 +08:00
|
|
|
def add_arguments(self, parser):
|
|
|
|
parser.add_argument('args', metavar='table_name', nargs='*',
|
|
|
|
help='Optional table names. Otherwise, settings.CACHES is used to '
|
|
|
|
'find cache tables.')
|
|
|
|
parser.add_argument('--database', action='store', dest='database',
|
|
|
|
default=DEFAULT_DB_ALIAS,
|
|
|
|
help='Nominates a database onto which the cache tables will be '
|
|
|
|
'installed. Defaults to the "default" database.')
|
2015-04-02 05:33:27 +08:00
|
|
|
parser.add_argument('--dry-run', action='store_true', dest='dry_run',
|
|
|
|
help='Does not create the table, just prints the SQL that would '
|
|
|
|
'be run.')
|
2014-06-07 04:39:33 +08:00
|
|
|
|
2013-01-06 06:43:01 +08:00
|
|
|
def handle(self, *tablenames, **options):
|
2012-03-11 01:50:59 +08:00
|
|
|
db = options.get('database')
|
2013-01-06 06:43:01 +08:00
|
|
|
self.verbosity = int(options.get('verbosity'))
|
2015-04-02 05:33:27 +08:00
|
|
|
dry_run = options.get('dry_run')
|
2013-01-06 06:43:01 +08:00
|
|
|
if len(tablenames):
|
|
|
|
# Legacy behavior, tablename specified as argument
|
|
|
|
for tablename in tablenames:
|
2015-04-02 05:33:27 +08:00
|
|
|
self.create_table(db, tablename, dry_run)
|
2013-01-06 06:43:01 +08:00
|
|
|
else:
|
|
|
|
for cache_alias in settings.CACHES:
|
2013-10-19 06:49:24 +08:00
|
|
|
cache = caches[cache_alias]
|
2013-01-06 06:43:01 +08:00
|
|
|
if isinstance(cache, BaseDatabaseCache):
|
2015-04-02 05:33:27 +08:00
|
|
|
self.create_table(db, cache._table, dry_run)
|
2013-01-06 06:43:01 +08:00
|
|
|
|
2015-04-02 05:33:27 +08:00
|
|
|
def create_table(self, database, tablename, dry_run):
|
2011-11-20 03:56:31 +08:00
|
|
|
cache = BaseDatabaseCache(tablename, {})
|
2015-02-19 15:27:58 +08:00
|
|
|
if not router.allow_migrate_model(database, cache.cache_model_class):
|
2013-01-06 06:43:01 +08:00
|
|
|
return
|
|
|
|
connection = connections[database]
|
|
|
|
|
|
|
|
if tablename in connection.introspection.table_names():
|
|
|
|
if self.verbosity > 0:
|
|
|
|
self.stdout.write("Cache table '%s' already exists." % tablename)
|
2011-11-20 03:56:31 +08:00
|
|
|
return
|
2013-01-06 06:43:01 +08:00
|
|
|
|
2007-08-16 14:06:55 +08:00
|
|
|
fields = (
|
|
|
|
# "key" is a reserved word in MySQL, so use "cache_key" instead.
|
|
|
|
models.CharField(name='cache_key', max_length=255, unique=True, primary_key=True),
|
|
|
|
models.TextField(name='value'),
|
|
|
|
models.DateTimeField(name='expires', db_index=True),
|
|
|
|
)
|
|
|
|
table_output = []
|
|
|
|
index_output = []
|
2007-08-20 09:03:33 +08:00
|
|
|
qn = connection.ops.quote_name
|
2007-08-16 14:06:55 +08:00
|
|
|
for f in fields:
|
2009-12-22 23:18:51 +08:00
|
|
|
field_output = [qn(f.name), f.db_type(connection=connection)]
|
2013-05-27 10:47:50 +08:00
|
|
|
field_output.append("%sNULL" % ("NOT " if not f.null else ""))
|
2007-08-16 14:06:55 +08:00
|
|
|
if f.primary_key:
|
|
|
|
field_output.append("PRIMARY KEY")
|
2008-06-30 12:46:59 +08:00
|
|
|
elif f.unique:
|
|
|
|
field_output.append("UNIQUE")
|
2007-08-16 14:06:55 +08:00
|
|
|
if f.db_index:
|
2013-05-17 22:33:36 +08:00
|
|
|
unique = "UNIQUE " if f.unique else ""
|
2013-10-18 08:24:41 +08:00
|
|
|
index_output.append("CREATE %sINDEX %s ON %s (%s);" %
|
2010-02-11 20:21:46 +08:00
|
|
|
(unique, qn('%s_%s' % (tablename, f.name)), qn(tablename),
|
2007-08-20 09:03:33 +08:00
|
|
|
qn(f.name)))
|
2007-08-16 14:06:55 +08:00
|
|
|
table_output.append(" ".join(field_output))
|
2007-08-20 09:03:33 +08:00
|
|
|
full_statement = ["CREATE TABLE %s (" % qn(tablename)]
|
2007-08-16 14:06:55 +08:00
|
|
|
for i, line in enumerate(table_output):
|
2013-11-04 02:08:55 +08:00
|
|
|
full_statement.append(' %s%s' % (line, ',' if i < len(table_output) - 1 else ''))
|
2007-08-16 14:06:55 +08:00
|
|
|
full_statement.append(');')
|
2014-03-22 18:02:00 +08:00
|
|
|
|
2015-04-02 05:33:27 +08:00
|
|
|
full_statement = "\n".join(full_statement)
|
|
|
|
|
|
|
|
if dry_run:
|
|
|
|
self.stdout.write(full_statement)
|
|
|
|
for statement in index_output:
|
|
|
|
self.stdout.write(statement)
|
|
|
|
return
|
|
|
|
|
2014-03-22 18:02:00 +08:00
|
|
|
with transaction.atomic(using=database,
|
|
|
|
savepoint=connection.features.can_rollback_ddl):
|
2014-01-09 23:05:15 +08:00
|
|
|
with connection.cursor() as curs:
|
|
|
|
try:
|
2015-04-02 05:33:27 +08:00
|
|
|
curs.execute(full_statement)
|
2014-01-09 23:05:15 +08:00
|
|
|
except DatabaseError as e:
|
|
|
|
raise CommandError(
|
|
|
|
"Cache table '%s' could not be created.\nThe error was: %s." %
|
|
|
|
(tablename, force_text(e)))
|
|
|
|
for statement in index_output:
|
|
|
|
curs.execute(statement)
|
2014-03-22 18:02:00 +08:00
|
|
|
|
2013-01-06 06:43:01 +08:00
|
|
|
if self.verbosity > 1:
|
|
|
|
self.stdout.write("Cache table '%s' created." % tablename)
|