Я создаю webapp, у которого есть дополнительный вход в Facebook. Пользователи, созданные через API Facebook, обрабатываются по-разному в нескольких точках моего приложения. Я хочу инкапсулировать эти различия в подкласс Person
который переопределяет методы.
class Person(Model):
def get_profile_picture(self):
return profile_pictures.url(self.picture)
class FacebookPerson(Person):
def get_profile_picture(self):
return 'http:/.../%s.jpg' % self.graph_id
Я бы хотел избежать неприятности, if self.graph_id
и просто запросить модель Person и получить правильный объект для каждого пользователя.
Я думал о взломе метакласса, чтобы добавить FacebookPerson в качестве базы. Очевидно, я бы хотел избежать такого вуду.
Я использую Flask и Flask-SQLAlchemy.
Общая идея заключалась бы в том, чтобы сохранить имя класса модели в метаданных в каждой строке, а когда вы создаете экземпляр объекта, сделайте что-то вроде:
def query(self):
# stuff
return model_class(data)
Чтобы сделать это в SQLAlchemy, вы можете взглянуть на то, чтобы сделать Person базовым классом чем-то вроде BasicPerson и FacebookPerson, а также в Person. init(), используйте метаданные для инициализации в соответствующий подкласс.
Например, идея была бы, чем когда этот запрос вернется, пользователь будет инициализирован в соответствующий подкласс:
user = session.query(Person).filter_by(name='james').first()
Вам, вероятно, потребуется немного изменить эту концепцию для SQLAlchemy (я не использовал ее в то время), но это общая идея.
Или вы можете сделать что-то вроде хранения метаданных в cookie с user_id, а затем, когда они снова войдут в систему, используйте метаданные для передачи соответствующего класса в запрос пользователя:
user = session.query(FacebookPerson).filter_by(name='james').first()
Если вы хотите, чтобы это было общим, чтобы метаданные имели смысл для клиентов, отличных от Python, вместо хранения имени класса модели, сохраните модель "object_type" и получите что-то в каждой клиентской библиотеке, которая сопоставляет object_types с классами.