2010-10-28 7 views
1

J'ai plusieurs modèles de profil utilisateur hérités d'une classe de base comme celui-ci:Django: Accès classe enfant d'un modèle abstrait

class BaseProfile(models.Model): 
    user = models.ForeignKey(User) 
    name = models.CharField(max_length=100) 
    ... 
    class Meta: 
     abstract = True 

class DoctorProfile(BaseProfile): 
    license_no = models.CharField(max_length=10) 
    ... 

class PharmacistProfile(BaseProfile): 
    pass 

Quand j'ai une instance d'utilisateur, je voudrais obtenir leur profil.

Je n'ai pas envie de vérifier si l'utilisateur a un profil un par un avec sth. comme ceci:

if user.doctorprofile_set.all().count() == 1: 
    return user.doctorprofile_set.all()[0] 
elif user.pharmacistprofile_set.all().count() == 1: 
    return user.pharmacistprofile_set.all()[0] 
... 

pour chaque profil est la meilleure façon que ce n'est pas sec et nécessite des requêtes supplémentaires sur la base de données.

Quelle est la meilleure façon de faire cela?

modifier: serait bien de définir AUTH_PROFILE_MODULE dans les paramètres pour pointer vers le modèle de base comme AUTH_PROFILE_MODULE = 'profiles.baseprofile' et être en mesure d'utiliser user.get_profile() sur chaque utilisateur avec différentes classes de profil dérivées du même profil de base.

+0

Puis-je demander Pourquoi avez-vous choisi d'utiliser l'héritage et non la composition ou l'agrégation comme moyen de délimitation entre différents types d'utilisateurs? Pourquoi une seule classe de profil avec un indicateur "is_a" ne serait-elle pas la bonne façon de procéder? Ensuite, vous pouvez utiliser get_profile(), pour une chose. –

+0

L'exemple que je fournis est un exemple simplifié. Dans le cas réel, il existe environ 10 types de profils différents avec de nombreux attributs communs et peu communs. Pour garder les modèles DRY, l'héritage me semble plus naturel. Et même si j'ai utilisé la composition, je crois que j'aurais toujours le même problème en essayant d'aller chercher le profil pour un utilisateur, n'est-ce pas? – omat

Répondre

1

Faire un OneToOneField au lieu d'un FK puis faire user.doctorprofile etc. Le OneToOne lancera une Foo.DoesNotExist ou Foo.MultipleObjectsReturned, bien que, si les choses tournent mal, alors soyez prêt à prendre ces exceptions

+0

merci, cela rendra les choses plus soignées. mais cette approche nécessite d'interroger chaque possibilité de profil un par un ce qui signifie des hits supplémentaires dans la base de données et pas très sec, car si un nouveau profil est introduit, un autre try ... except block devrait être ajouté au code qui récupère les profils. serait bien d'utiliser get_profile() sur la classe BaseProfile. Je vais mettre à jour ma question. – omat

+1

Je n'ai pas dit que c'était parfait. L'extension du modèle User dans Django ne sera pas plus agréable jusqu'au 1.3/1.4, je suppose. Et vous pouvez toujours ajouter du code (comme je le fais) qui met en cache le profil la première fois que cela est nécessaire et invalide ensuite sa clé lorsque le modèle est sauvegardé à nouveau –

+0

Eh bien, je viens du futur pour dire que jusqu'à Django 1.9 on n'a rien même proche de ça. –