# 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,
)
            return possible_databases[0]

        shard = self._get_shard(model, **hints)
        if shard:
            shard_group = getattr(model, 'django_sharding__shard_group', None)
            if not shard_group:
                raise DjangoShardingException('Unable to identify the shard_group for the {} model'.format(model))
            routing_strategy = self.get_read_db_routing_strategy(shard_group)
            return routing_strategy.pick_read_db(shard)
        return None

    def db_for_write(self, model, **hints):
        possible_databases = get_possible_databases_for_model(model=model)
        if len(possible_databases) == 1:
            return possible_databases[0]

        shard = self._get_shard(model, **hints)

        if shard:
            db_config = settings.DATABASES[shard]
            return db_config.get('PRIMARY', shard)
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Only allow relationships between two items which are both on only one database or
        between sharded items on the same shard.
        """

        object1_databases = get_possible_databases_for_model(model=obj1._meta.model)

# 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,
)

            return possible_databases[0]

        shard = self._get_shard(model, **hints)
        if shard:
            shard_group = getattr(model, 'django_sharding__shard_group', None)
            if not shard_group:
                raise DjangoShardingException('Unable to identify the shard_group for the {} model'.format(model))
            routing_strategy = self.get_read_db_routing_strategy(shard_group)
            return routing_strategy.pick_read_db(shard)
        return None

    def db_for_write(self, model, **hints):
        possible_databases = get_possible_databases_for_model(model=model)
        if len(possible_databases) == 1:
            return possible_databases[0]

        shard = self._get_shard(model, **hints)

        if shard:
            db_config = settings.DATABASES[shard]
            return db_config.get('PRIMARY', shard)
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Only allow relationships between two items which are both on only one database or
        between sharded items on the same shard.
        """

        object1_databases = get_possible_databases_for_model(model=obj1._meta.model)

        object2_databases = get_possible_databases_for_model(model=obj2._meta.model)