django-categories/categories/migration.py
2013-05-20 17:42:03 -05:00

120 lines
5.1 KiB
Python

from django.db import models, DatabaseError
from django.core.exceptions import ImproperlyConfigured
from django.utils.translation import ugettext_lazy as _
def migrate_app(sender, app, created_models=None, verbosity=False, *args, **kwargs):
"""
Migrate all models of this app registered
"""
from .fields import CategoryM2MField, CategoryFKField
from .models import Category
from .settings import FIELD_REGISTRY
import sys
import StringIO
org_stderror = sys.stderr
sys.stderr = StringIO.StringIO() # south will print out errors to stderr
try:
from south.db import db
except ImportError:
raise ImproperlyConfigured(_('%(dependency) must be installed for this command to work') %
{'dependency': 'South'})
# pull the information from the registry
if isinstance(app, basestring):
app_name = app
else:
app_name = app.__name__.split('.')[-2]
fields = [fld for fld in FIELD_REGISTRY.keys() if fld.startswith(app_name)]
# call the south commands to add the fields/tables
for fld in fields:
app_name, model_name, field_name = fld.split('.')
# Table is typically appname_modelname, but it could be different
# always best to be sure.
mdl = models.get_model(app_name, model_name)
if isinstance(FIELD_REGISTRY[fld], CategoryFKField):
try:
db.start_transaction()
table_name = mdl._meta.db_table
FIELD_REGISTRY[fld].default = -1
db.add_column(table_name, field_name, FIELD_REGISTRY[fld], keep_default=False)
db.commit_transaction()
if verbosity:
print (_('Added ForeignKey %(field_name) to %(model_name)') %
{'field_name': field_name, 'model_name': model_name})
except DatabaseError, e:
db.rollback_transaction()
if "already exists" in str(e):
if verbosity > 1:
print (_('ForeignKey %(field_name) to %(model_name) already exists') %
{'field_name': field_name, 'model_name': model_name})
else:
sys.stderr = org_stderror
raise e
elif isinstance(FIELD_REGISTRY[fld], CategoryM2MField):
table_name = '%s_%s' % (mdl._meta.db_table, 'categories')
try:
db.start_transaction()
db.create_table(table_name, (
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
(model_name, models.ForeignKey(mdl, null=False)),
('category', models.ForeignKey(Category, null=False))
))
db.create_unique(table_name, ['%s_id' % model_name, 'category_id'])
db.commit_transaction()
if verbosity:
print (_('Added Many2Many table between %(model_name) and %(category_table)') %
{'model_name': model_name, 'category_table': 'category'})
except DatabaseError, e:
db.rollback_transaction()
if "already exists" in str(e):
if verbosity > 1:
print (_('Many2Many table between %(model_name) and %(category_table) already exists') %
{'model_name': model_name, 'category_table': 'category'})
else:
sys.stderr = org_stderror
raise e
sys.stderr = org_stderror
def drop_field(app_name, model_name, field_name):
"""
Drop the given field from the app's model
"""
# Table is typically appname_modelname, but it could be different
# always best to be sure.
from .fields import CategoryM2MField, CategoryFKField
from .settings import FIELD_REGISTRY
try:
from south.db import db
except ImportError:
raise ImproperlyConfigured(_('%(dependency) must be installed for this command to work') %
{'dependency': 'South'})
mdl = models.get_model(app_name, model_name)
fld = '%s.%s.%s' % (app_name, model_name, field_name)
if isinstance(FIELD_REGISTRY[fld], CategoryFKField):
print (_('Dropping ForeignKey %(field_name) from %(model_name)') %
{'field_name': field_name, 'model_name': model_name})
try:
db.start_transaction()
table_name = mdl._meta.db_table
db.delete_column(table_name, field_name)
db.commit_transaction()
except DatabaseError, e:
db.rollback_transaction()
raise e
elif isinstance(FIELD_REGISTRY[fld], CategoryM2MField):
print (_('Dropping Many2Many table between %(model_name) and %(category_table)') %
{'model_name': model_name, 'category_table': 'category'})
try:
db.start_transaction()
db.delete_table(table_name, cascade=False)
db.commit_transaction()
except DatabaseError, e:
db.rollback_transaction()
raise e