Reputation: 4884
I have a database that we use for all of our customers. Each customer has a set of tables, postfixed with their customer ID:
It is set up with "manual" SQL statements, but I am undertaking an effort to port it to SQLAlchemy for easier maintainability.
I would prefer to use the declarative syntax, but is there any way I can dynamically set the __tablename__
value of a model? And what happens if I need to access multiple customers in a threaded environment (we will most likely use different processes, but I'd rather cover it up front just in case).
Besides the tablename itself, all relationships (straightforward single key foreign keys) would also have to be mapped correctly between tables.
Upvotes: 0
Views: 155
Reputation: 23236
One approach is to factory up all of the classes you require for a customer. Something like the following ... (this is just a sketch!)
class customer_classes:
# create the base class
base = declarative_base(metadata=metadata)
def __init__(self, metadata, customer_id):
class analytics(self.base):
__tablename__ = 'analytics_{}'.format(customer_id)
__mapper_args__ = ...
class embeds(self.base):
__tablename__ = 'analytics_{}'.format(customer_id)
__mapper_args__ = ...
class downloads(self.base):
__tablename__ = 'analytics_{}'.format(customer_id)
__mapper_args__ = ...
# now lets assign all these classes to attributes
import inspect
defined_classes = [cls for cls in locals().values()
if inspect.isclass(cls) and issubclass(cls, base)]
self.__dict__.update({cls.__name__: cls for cls in defined_classes})
# now we can create a set of classes for customer 123
customer_model = customer_classes(123)
session.query(customer_model. analytics).all()
# you can just as easily work with another customer at the same time in the same session
another_model = customer_classes(456)
session.query(another_model.analytics).all()
Upvotes: 2