# Path: django_sharding_library/exceptions.py
# class DjangoShardingException(Exception):
#     pass
# 
# class InvalidMigrationException(DjangoShardingException):
#     pass
# 
# Path: django_sharding_library/utils.py
# def is_model_class_on_database(model, database):
#     specific_database = getattr(model, 'django_sharding__database', None)
#     is_sharded = getattr(model, 'django_sharding__is_sharded', False)
# 
#     if specific_database and is_sharded:
#         raise DjangoShardingException('Model marked as both sharded and on a single database, unable to determine where to run migrations for {}.'.format(model.__class__.__name__))
# 
#     if specific_database:
#         return getattr(model, 'django_sharding__database') == database
# 
#     if is_sharded:
#         shard_group = getattr(model, 'django_sharding__shard_group', None)
#         if shard_group:
#             return settings.DATABASES[database]['SHARD_GROUP'] == shard_group
#         raise DjangoShardingException("Unable to determine what database the model is on as the shard group of {} is unknown.".format(model.__class__.__name__))
# 
#     return database == "default"
# 
# def get_database_for_model_instance(instance):
#     if instance._state.db:
#         return instance._state.db
# 
#     model = instance._meta.model
#     possible_databases = get_possible_databases_for_model(model=model)
#     if len(possible_databases) == 1:
#         return possible_databases[0]
#     elif len(possible_databases) == 0:
#         pass
#     else:
#         return instance.get_shard()
# 
#     raise DjangoShardingException("Unable to deduce datbase for model instance")
# 
# def get_possible_databases_for_model(model):
#     return [
#         database for database in settings.DATABASES
#         if is_model_class_on_database(model=model, database=database)
#     ]


from django.apps import apps
from django.conf import settings
from django_sharding_library.exceptions import DjangoShardingException, InvalidMigrationException
from django_sharding_library.utils import (
    is_model_class_on_database,
    get_database_for_model_instance,
    get_possible_databases_for_model,
)
                if is_model_class_on_database(model=model, database=db):
                    return True
            return False

        # Sometimes, when extending models from another app i.e. the User Model, the app label
        # is the app label of the app where the change is defined but to app with the model is
        # passed in with the model name.
        try:
            if "." in model_name:
                _app_label = model_name.split('.')[0]
                app = apps.get_app_config(_app_label)
                model = app.get_model(model_name[len(_app_label) + 1:])
            else:
                app = apps.get_app_config(app_label)
                model = app.get_model(model_name)
        except LookupError as exception:
            deleted_model_settings = getattr(settings, 'DJANGO_SHARDING_SETTINGS', {}).get('DELETED_MODELS', {})
            entry = "{}.{}".format(app_label, model_name) if "." not in model_name else model_name
            if entry not in deleted_model_settings:
                raise exception
            deleted_model_data = deleted_model_settings[entry]
            if deleted_model_data is None or ("shard_group" not in deleted_model_data and "database" not in deleted_model_data):
                return db == "default"
            elif "database" in deleted_model_data:
                return db == deleted_model_data["database"]
            else:
                return settings.DATABASES[db]['SHARD_GROUP'] == deleted_model_data["shard_group"]

        try:
            return is_model_class_on_database(model=model, database=db)

# Path: django_sharding_library/exceptions.py
# class DjangoShardingException(Exception):
#     pass
# 
# class InvalidMigrationException(DjangoShardingException):
#     pass
# 
# Path: django_sharding_library/utils.py
# def is_model_class_on_database(model, database):
#     specific_database = getattr(model, 'django_sharding__database', None)
#     is_sharded = getattr(model, 'django_sharding__is_sharded', False)
# 
#     if specific_database and is_sharded:
#         raise DjangoShardingException('Model marked as both sharded and on a single database, unable to determine where to run migrations for {}.'.format(model.__class__.__name__))
# 
#     if specific_database:
#         return getattr(model, 'django_sharding__database') == database
# 
#     if is_sharded:
#         shard_group = getattr(model, 'django_sharding__shard_group', None)
#         if shard_group:
#             return settings.DATABASES[database]['SHARD_GROUP'] == shard_group
#         raise DjangoShardingException("Unable to determine what database the model is on as the shard group of {} is unknown.".format(model.__class__.__name__))
# 
#     return database == "default"
# 
# def get_database_for_model_instance(instance):
#     if instance._state.db:
#         return instance._state.db
# 
#     model = instance._meta.model
#     possible_databases = get_possible_databases_for_model(model=model)
#     if len(possible_databases) == 1:
#         return possible_databases[0]
#     elif len(possible_databases) == 0:
#         pass
#     else:
#         return instance.get_shard()
# 
#     raise DjangoShardingException("Unable to deduce datbase for model instance")
# 
# def get_possible_databases_for_model(model):
#     return [
#         database for database in settings.DATABASES
#         if is_model_class_on_database(model=model, database=database)
#     ]


# Path: django_sharding_library/router.py
from django.apps import apps
from django.conf import settings
from django_sharding_library.exceptions import DjangoShardingException, InvalidMigrationException
from django_sharding_library.utils import (
    is_model_class_on_database,
    get_database_for_model_instance,
    get_possible_databases_for_model,
)

                if is_model_class_on_database(model=model, database=db):
                    return True
            return False

        # Sometimes, when extending models from another app i.e. the User Model, the app label
        # is the app label of the app where the change is defined but to app with the model is
        # passed in with the model name.
        try:
            if "." in model_name:
                _app_label = model_name.split('.')[0]
                app = apps.get_app_config(_app_label)
                model = app.get_model(model_name[len(_app_label) + 1:])
            else:
                app = apps.get_app_config(app_label)
                model = app.get_model(model_name)
        except LookupError as exception:
            deleted_model_settings = getattr(settings, 'DJANGO_SHARDING_SETTINGS', {}).get('DELETED_MODELS', {})
            entry = "{}.{}".format(app_label, model_name) if "." not in model_name else model_name
            if entry not in deleted_model_settings:
                raise exception
            deleted_model_data = deleted_model_settings[entry]
            if deleted_model_data is None or ("shard_group" not in deleted_model_data and "database" not in deleted_model_data):
                return db == "default"
            elif "database" in deleted_model_data:
                return db == deleted_model_data["database"]
            else:
                return settings.DATABASES[db]['SHARD_GROUP'] == deleted_model_data["shard_group"]

        try:
            return is_model_class_on_database(model=model, database=db)

        except DjangoShardingException as e: