2011-06-21 3 views
1

Je crée une application Web avec une connexion Facebook facultative. Les utilisateurs créés via l'API Facebook sont traités différemment à plusieurs points de mon application. Je veux encapsuler ces différences dans une sous-classe de Person qui remplace les méthodes.Comment puis-je choisir le modèle déclaratif à instancier, en fonction des informations sur les lignes?

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 

Je voudrais éviter le if self.graph_id méchant et juste interroger le modèle de personne et d'obtenir le bon objet pour chaque utilisateur.

J'ai pensé à pirater la métaclasse pour ajouter le FacebookPerson comme base. Évidemment, je voudrais éviter un tel vaudou. J'utilise Flask et Flask-SQLAlchemy.

Répondre

1

L'idée générale serait de stocker le nom de la classe du modèle sous forme de métadonnées dans chaque ligne, et lorsque vous instancier l'objet, faire quelque chose comme:

def query(self): 
    # stuff 
    return model_class(data) 

Pour ce faire, dans SQLAlchemy, vous pouvez regarder à faire Associez la classe de base à quelque chose comme BasicPerson et FacebookPerson, et en personne. init(), utilisez les métadonnées pour initialiser la sous-classe appropriée.

Par exemple, l'idée serait que lorsque cette requête retourne, l'utilisateur aura été initialisé à la sous-classe appropriée:

user = session.query(Person).filter_by(name='james').first() 

Vous aurez probablement besoin de modifier ce concept un peu pour SQLAlchemy (paradis I » Je l'ai utilisé dans un moment), mais c'est l'idée générale.

Ou, vous pouvez faire quelque chose comme stocker les métadonnées dans un cookie avec le user_id, puis lorsqu'ils se connectent à nouveau, utiliser les métadonnées pour passer la classe appropriée à la requête de l'utilisateur:

user = session.query(FacebookPerson).filter_by(name='james').first() 

Si vous voulez que ce soit générique pour que les métadonnées soient significatives pour les clients non-Python, au lieu de stocker le nom de classe du modèle, stocker le "object_type" du modèle et avoir quelque chose dans chaque bibliothèque client qui associe object_types aux classes.

Questions connexes