Created for
# create new Django project
django-admin startproject using_legacy_db
# create the app, which will use the legacy db:
python manage.py startapp music_catalog_app
# create the legacy db:
CREATE DATABASE music_catalog_legacy_db;
GRANT ALL PRIVILEGES ON music_catalog_legacy_db.* TO 'django_admin'@'localhost';
FLUSH PRIVILEGES;
mysql -u django_admin -p music_catalog_legacy_db < music_catalog_legacy_db.rowdump.sql
db_for_read(model, **hints)db_for_write(model, **hints)allow_relation(obj1, obj2, **hints)allow_migrate(db, app_label, model_name=None, **hints)db_for_read(model, **hints)db_for_write(model, **hints)allow_relation(obj1, obj2, **hints)allow_migrate(db, app_label, model_name=None, **hints)allow_migrate(db, app_label, model_name=None, **hints)allow_migrate() method can also be used to determine the availability of a model on a given database.allow_migrate() returns False, any migration operations for the model_name will be silently skipped when running migrate on the db.
class MusicCatalogLegacyDbRouter:
"""
A router to control all database operations on models
in the music_catalog_app.
"""
def db_for_read(self, model, **hints):
# Attempts to read music_catalog_app go to music_catalog_legacy_db.
if model._meta.app_label == 'music_catalog_app':
return 'music_catalog_legacy_db'
return None
def db_for_write(self, model, **hints):
# Attempts to write music_catalog_app go to music_catalog_legacy_db.
if model._meta.app_label == 'music_catalog_app':
return 'music_catalog_legacy_db'
return None
def allow_relation(self, obj1, obj2, **hints):
# Allow any relation if both models are part of the worlddata app
if obj1._meta.app_label == 'music_catalog_app' and \
obj2._meta.app_label == 'music_catalog_app':
return True
# Allow if neither is part of worlddata app
elif 'music_catalog_app' not in [obj1._meta.app_label, obj2._meta.app_label]:
return True
# by default return None - "undecided"
def allow_migrate(self, db, app_label, model_name=None, **hints):
# allow migrations on the "default" (django related data) DB
if db == 'default' and app_label != 'music_catalog_app':
return True
# allow migrations on the legacy database too
# this will enable us to actually alter the database schema of the legacy DB.
if db == 'music_catalog_legacy_db' and app_label == "music_catalog_app":
return True
return False
DATABASE_ROUTERS = ['path.to.DBRouter1', 'path.to.DBRouter2']path.to. with the actual Python path to the module where a router is defined
# the path, relative to the project: 'using_legacy_db/music_catalog_legacy_db_router.py'
DATABASE_ROUTERS = ['using_legacy_db.music_catalog_legacy_db_router.MusicCatalogLegacyDbRouter']
# Make sure that only the default migrations will be made:
python manage.py showmigrations
# if everything ok, then migrate:
python manage.py migrate
inspectdb
python manage.py inspectdb [--database DATABASE] [table [table ...]]
# to get all options:
python manage.py inspectdb --help
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'music_catalog_legacy_db': {
'ENGINE': 'django.db.backends.mysql',
'OPTIONS': {
'read_default_file': os.path.join(BASE_DIR, 'using_legacy_db/music_catalog_legacy_db.cnf'),
},
}
}
[client]
database = music_catalog_legacy_db
user = django_admin
password = 123
default-character-set = utf8
python manage.py inspectdb --database=music_catalog_legacy_db > music_catalog_legacy_db_inspectdb.py
class AlbumArtist(models.Model):
album = models.ForeignKey(Album, models.DO_NOTHING, primary_key=True)
artist = models.ForeignKey('Artist', models.DO_NOTHING)
class Meta:
managed = False
db_table = 'album_artist'
unique_together = (('album', 'artist'),)
class Album(models.Model):
# ...
artist = models.ManyToManyField(Artist)
# now, you can remove AlbumArtist table
This field type is a guess.' next to the field in the generated model.id = models.IntegerField(primary_key=True)_field' to the attribute name and set the db_column attribute to the real field name (e.g., pass, class, or for).
pass_field = models.IntegerField(db_column='pass')
Field renamed because it was a Python reserved word.' next to the field.These slides are based on
customised version of
framework