2010-09-22 25 views
6

Mon models.py:différents profils utilisateurs avec django-profils et django-inscription

USER_TYPES = (                                         
    ('D', 'Demo' ),                                        
    ('F', 'Free' ), 
    ('P', 'Premium'),                                       
)                                                                                         

class BaseProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    user_type = models.CharField(max_length=1, blank=True, choices=USER_TYPES)                           

class DemoProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    demo  = models.CharField(max_length=10, blank=True) 
    ... 

class FreeProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    free  = models.CharField(max_length=10, blank=True) 
    ... 

class PremiumProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    premium = models.CharField(max_length=10, blank=True) 
    ... 

class ProxyProfile(BaseProfile):                                     
    class Meta:                                         
     proxy = True    
    def get_profile(self):                                                                                                                                                              
     if self.user_type == 'D':                                    
      return DemoProfile._default_manager.get(user__id__exact=self.user_id)                        
     elif self.user_type == 'F':                                    
      return FreeProfile._default_manager.get(user__id__exact=self.user_id)                        
     else:                                         
      return PremiumProfile._default_manager.get(user__id__exact=self.user_id)                           

-je utiliser BaseProfile à la carte user_id à user_type spécifique. Je voulais utiliser ProxyProfile comme proxy qui charge les profils en fonction user_type à ModelForm comme indiqué ci-dessous

Contenu de mon forms.py:

class ProfileForm(ModelForm):                                      
...                                             
    class Meta:                                         
     model = ProxyProfile                                     
     exclude = ('user','user_type') 
... 

ProfileForm est fourni django-profils à l'aide du code ci-dessous dans urls.py:

urlpatterns += patterns('',                                      
    url(r'^profiles/edit/', edit_profile,                                   
     {'form_class': ProfileForm},                                    
     name='profiles_edit_profile'),                                   
    (r'^profiles/',include('profiles.urls')),                                  
) 

J'ai aussi mis en settings.py:

AUTH_PROFILE_MODULE = 'main.ProxyProfile' 

Lors de l'enregistrement de l'utilisateur, toutes les données db sont correctement remplies (tout semble OK). Je registre en utilisant le formulaire passé à django-inscription:

urlpatterns += patterns('',                                      
    url(r'^register/$', register,                                     
     {'form_class': UserRegistrationForm},                                  
     name='registration.views.register'),                                  
    (r'', include('registration.urls')),                                   
) 

de forms.py:

class UserRegistrationForm(RegistrationFormUniqueEmail, RegistrationFormTermsOfService):                       
    utype  = forms.ChoiceField(choices=USER_CHOICES)                        

    def save(self, profile_callback=None):                                  
     new_user = RegistrationProfile.objects.create_inactive_user(username=self.cleaned_data['username'], 
                    password.self.cleaned_data['password1'],                  
                    email=self.cleaned_data['email'],                    
                    )                            
     new_base_profile = BaseProfile(user=new_user, user_type=self.cleaned_data['utype'])                      
     if self.cleaned_data['utype'] == "D":                                  
      new_profile = DemoProfile(user=new_user)                                
     if self.cleaned_data['utype'] == "F":                                  
      new_profile = FreeProfile(user=new_user)                                
     if self.cleaned_data['utype'] == "P":                                  
      new_profile = PremiumProfile(user=new_user)                                
     new_profile.save()                                      
     new_base_profile.save()                                     
     return new_user     

et la phase d'enregistrement fonctionne bien.

J'ai un problème avec les pages de modification/détails de profil. Mes profils filtrés dans le modèle ProxyProfile et utilisés comme FormModel dans ProfileForm ne sont pas rendus (je ne peux pas voir les champs spécifiques au profil ne sont pas rendus à la page HTML) Peut-être qu'il y a un autre moyen (plus comme Django manière :)) à faire ce (sélectionner et rendre le modèle de profil en fonction du champ user_type qui est lié au modèle User).

Merci à l'avance :)

+0

Je vois que vous avez utilisé un modèle de procuration. N'importe quelle raison pour laquelle vous ne pouvez pas faire de BaseProfile une classe de base abstraite (voir http://docs.djangoproject.com/fr/1.2/topics/db/models/#abstract-base-classes) pour que Django charge le bon sous-type pour vous? –

+0

J'ai utilisé un modèle de proxy basé sur BaseProfile parce que je voudrais remplacer la méthode get_profile de la classe User. get_profile() est appelée par l'application django-profiles pour récupérer le modèle de profil associé à l'utilisateur. Le problème est que j'ai différents modèles de profil pour différents utilisateurs (mais un utilisateur <-> un type de profil). –

Répondre

5

Ok, finalement je l'ai eu une idée comment je peux le faire :)

Dans mon models.py:

class BaseManager(models.Manager):                                    
    def get(self, **kwargs):                                      
     self.u = kwargs['user__id__exact']                                  
     self.bt = BaseProfile.manager.get(user__id__exact=self.u)                             
     if self.bt.user_type == 'F':                                    
      return FreeProfile.objects.get(pk=self.u)                                
     elif self.bt.user_type == 'I':                                   
      return PremiumProfile.objects.get(pk=self.u)                                
     else:                                          
      return None                                       

class BaseProfile(models.Model):                                     
    objects = BaseManager()                                      
    manager = UserManager()                                      
    user  = models.OneToOneField(User, primary_key=True)                              
    user_type = models.CharField(max_length=1, blank=True, choices=USER_TYPES)                         

class FreeProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    free  = models.CharField(max_length=10, blank=True) 
    ... 

class PremiumProfile(models.Model):                                     
    user  = models.OneToOneField(User, primary_key=True)                              
    premium = models.CharField(max_length=10, blank=True) 
    ... 

Dans le Gestionnaire personnalisé - BaseManager Je renvoie l'objet profile en écrasant la méthode get() utilisée par get_profile. Je dois utiliser UserManager nommé simplement 'manager' pour empêcher l'appel récursif du gestionnaire personnalisé lors de l'affectation de self.bt

OK, c'est à mi-chemin pour réaliser ce que je veux, maintenant je peux voir différents profils attachés aux utilisateurs en utilisant django -applications

Ensuite, je souhaite utiliser ModelForm pour préparer un formulaire d'édition pour les profils utilisateur. Les utilisateurs peuvent avoir des profils différents, donc je l'ai appliqué tour de magie présenté dans cet extrait: http://djangosnippets.org/snippets/2081/

Et maintenant, dans mon forms.py je:

class FreeForm(forms.ModelForm):                                     
    class Meta:                                         
     model = FreeProfile                                      


class PremiumForm(forms.ModelForm):                                     
    class Meta:                                         
     model = PremiumProfile   

suivant, les formes simples de modèle pour chaque profil sont assemblés dans ProfileForm:

class ProfileForm(ModelForm):                                      
    def __init__(self, *args, **kwargs):                                   
    self.user = kwargs['instance'].user                                  
    profile_kwargs = kwargs.copy()                                   
    profile_kwargs['instance'] = self.user                                 
    self.bt = BaseProfile.manager.get(user__id__exact=self.user.id)                           
    if self.bt.user_type == 'F':                                    
     self.profile_fields = FreeForm(*args, **profile_kwargs)                            
    elif self.bt.user_type == 'P':                                   
     self.profile_fields = PremiumForm(*args, **profile_kwargs)                            
    super(ProfileForm, self).__init__(*args, **kwargs)                              
    self.fields.update(self.profile_fields.fields)                               
    self.initial.update(self.profile_fields.initial) 

    class Meta:                                                                          
     model = BaseProfile  

    def save(self): 
     ... 

Dans les paramètres.py:

AUTH_PROFILE_MODULE = 'main.BaseProfile' 

Et cela fonctionne comme un charme, mais je me demande si c'est la façon de Django pour obtenir le soutien de plusieurs profils différents en utilisant des profils de django-? Cela m'inquiète de devoir utiliser get() quelques fois de plus avant de rendre les détails du profil ou de modifier le formulaire.

Mais au bout de 4 jours de lutte avec Django pour obtenir ce que je peux faire enfin bien dormir ce soir :)

Vive