def handle_app(self, app, **options): appname = app.__name__ print 'handling app %s' % appname for obj in [getattr(app, name) for name in dir(app)]: if not isclass(obj): continue if not issubclass(obj, models.Model): continue if not is_multilingual_model(obj): continue print 'altering model %s' % obj table = obj._meta.translation_model._meta.db_table db.debug = True db.add_column(table, 'language_code', models.CharField(max_length=15, blank=True, choices=get_language_choices(), db_index=True) ) # migrate the model # This is TERRIBLE for performance, but whatever... print 'migrating data' tempfield = models.IntegerField(blank=False, null=False, choices=get_language_choices(), db_index=False) tempfield.contribute_to_class(obj._meta.translation_model, 'language_id') for row in obj.objects.all(): for translation in row.translations.all(): translation.language_code = get_code_by_id(translation.language_id) translation.save() db.create_index(table, ['language_code', 'master_id']) print 'deleting language_id column' db.delete_unique(table, ['language_id', 'master_id']) db.delete_column(table, 'language_id')
def validate_admin_registration(cls, model): """ Validates a class specified as a model admin. Right now this means validating prepopulated_fields, as for multilingual models DM handles them by itself. """ if not is_multilingual_model(model): return from django.contrib.admin.validation import check_isdict, check_isseq opts = model._meta # this is heavily based on django.contrib.admin.validation. if hasattr(cls, '_dm_prepopulated_fields'): check_isdict(cls, '_dm_prepopulated_fields', cls.prepopulated_fields) for field, val in cls._dm_prepopulated_fields.items(): f = get_field(cls, model, opts, 'prepopulated_fields', field) if isinstance(f, (models.DateTimeField, models.ForeignKey, models.ManyToManyField)): raise ImproperlyConfigured( "'%s.prepopulated_fields['%s']' " "is either a DateTimeField, ForeignKey or " "ManyToManyField. This isn't allowed." % (cls.__name__, field)) check_isseq(cls, "prepopulated_fields['%s']" % field, val) for idx, f in enumerate(val): get_field(cls, model, opts, "prepopulated_fields['%s'][%d]" % (f, idx), f)
def validate_admin_registration(cls, model): """ Validates a class specified as a model admin. Right now this means validating prepopulated_fields, as for multilingual models DM handles them by itself. """ if not is_multilingual_model(model): return from django.contrib.admin.validation import check_isdict, check_isseq opts = model._meta # this is heavily based on django.contrib.admin.validation. if hasattr(cls, '_dm_prepopulated_fields'): check_isdict(cls, '_dm_prepopulated_fields', cls.prepopulated_fields) for field, val in cls._dm_prepopulated_fields.items(): f = get_field(cls, model, opts, 'prepopulated_fields', field) if isinstance(f, (models.DateTimeField, models.ForeignKey, models.ManyToManyField)): raise ImproperlyConfigured("'%s.prepopulated_fields['%s']' " "is either a DateTimeField, ForeignKey or " "ManyToManyField. This isn't allowed." % (cls.__name__, field)) check_isseq(cls, "prepopulated_fields['%s']" % field, val) for idx, f in enumerate(val): get_field(cls, model, opts, "prepopulated_fields['%s'][%d]" % (f, idx), f)
def handle_app(self, app, **options): appname = app.__name__ print 'handling app %s' % appname for obj in [getattr(app, name) for name in dir(app)]: if not isclass(obj): continue if not issubclass(obj, models.Model): continue if not is_multilingual_model(obj): continue print 'altering model %s' % obj table = obj._meta.translation_model._meta.db_table db.debug = True # do this in a transaction db.start_transaction() # first add the column with nullable values, and no index lc_field = models.CharField(max_length=15, blank=True, null=True) db.add_column(table, 'language_code', lc_field) # migrate the model print 'migrating data' # do the conversion server-side # all modern RDBMSs support the case statement update_sql = "UPDATE %s SET language_code = (CASE language_id %s END)" % (table, ' '.join( "WHEN %d THEN '%s'" % (lid, get_code_by_id(lid)) for lid in range(1, len(settings.LANGUAGES) + 1) ) ) db.execute(update_sql) print 'deleting language_id column' db.delete_unique(table, ['language_id', 'master_id']) db.delete_column(table, 'language_id') print 'setting up constraints and indices' # alter the column to set not null lc_field.null = False db.alter_column(table, 'language_code', lc_field) ## we don't really need this indexed. all queries should hit the unique index #db.create_index(table, ['language_code']) # and create a unique index for master & language db.create_unique(table, ['language_code', 'master_id']) # south might fail to commit if we don't do it explicitly db.commit_transaction()
def handle_app(self, app, **options): appname = app.__name__ print 'handling app %s' % appname for obj in [getattr(app, name) for name in dir(app)]: if not isclass(obj): continue if not issubclass(obj, models.Model): continue if not is_multilingual_model(obj): continue print 'altering model %s' % obj table = obj._meta.translation_model._meta.db_table db.debug = True # do this in a transaction db.start_transaction() # first add the column with nullable values, and no index lc_field = models.CharField(max_length=15, blank=True, null=True) db.add_column(table, 'language_code', lc_field) # migrate the model print 'migrating data' # do the conversion server-side # all modern RDBMSs support the case statement update_sql = "UPDATE %s SET language_code = (CASE language_id %s END)" % ( table, ' '.join("WHEN %d THEN '%s'" % (lid, get_code_by_id(lid)) for lid in range(1, len(settings.LANGUAGES) + 1))) db.execute(update_sql) print 'deleting language_id column' db.delete_unique(table, ['language_id', 'master_id']) db.delete_column(table, 'language_id') print 'setting up constraints and indices' # alter the column to set not null lc_field.null = False db.alter_column(table, 'language_code', lc_field) ## we don't really need this indexed. all queries should hit the unique index #db.create_index(table, ['language_code']) # and create a unique index for master & language db.create_unique(table, ['language_code', 'master_id']) # south might fail to commit if we don't do it explicitly db.commit_transaction()