2010-09-22 18 views
6

Mi models.py:diferentes perfiles de usuario con Django Django y perfiles registro

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)                           

yo uso BaseProfile para mapear user_id a user_type específica. Quería utilizar ProxyProfile como apoderado que carga user_type dependiendo perfiles a ModelForm como se muestra a continuación

contenido de mi forms.py: se proporciona

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

ProfileForm a Django perfiles utilizando siguiente código en urls.py:

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

también me he fijado en settings.py:

AUTH_PROFILE_MODULE = 'main.ProxyProfile' 

Durante el registro del usuario, todos los datos de db se llenan correctamente (parece que todo está bien). me registro usando pasó a django-registro formulario:

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     

y registro de fase funciona bien.

Tengo un problema con las páginas de edición/detalles de perfil. Mis perfiles filtrados en el modelo ProxyProfile y utilizados como FormModel en ProfileForm no se representan (no puedo ver los campos específicos del perfil no se representan en la página HTML) Quizás haya alguna otra manera (más como Django way :)) de hacer (seleccione y represente el modelo de perfil según el campo user_type relacionado con el modelo de usuario).

Gracias de antemano :)

+0

Veo que ha usado un modelo de poder. Cualquier motivo por el que no se pueda simplemente hacer que BaseProfile sea una clase base abstracta (consulte http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes) para que Django cargue correctamente subtipo para usted? –

+0

He utilizado un modelo de proxy basado en Perfil Base porque me gustaría sobrescribir el método get_profile de la clase Usuario. La aplicación django-profiles llama a get_profile() para buscar el modelo de perfil asociado con el usuario. El problema es que tengo diferentes modelos de perfil para diferentes usuarios (pero un usuario <-> un tipo de perfil). –

Respuesta

5

Ok, finalmente he tenido una idea de cómo puedo hacer esto :)

En mi 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) 
    ... 

En gestor de encargo - BaseManager Devuelvo el objeto de perfil sobrescribiendo el método get() utilizado por get_profile. Tengo que usar el UserManager llamado simplemente 'manager' para evitar la llamada recursiva del administrador personalizado al asignar self.bt

OK, esto está a mitad de camino para lograr lo que quiero, ahora puedo ver diferentes perfiles adjuntos a los usuarios que usan django aplicación de perfiles

A continuación, deseo usar ModelForm para preparar el formulario de edición para los perfiles de usuario. Los usuarios pueden tener diferentes perfiles de modo que he aplicado el truco mágico se presenta en este fragmento: http://djangosnippets.org/snippets/2081/

Y ahora en mi forms.py tengo:

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


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

lado, los modelos de formularios simples para cada perfil se ensamblan en 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): 
     ... 

En la configuración.PY:

AUTH_PROFILE_MODULE = 'main.BaseProfile' 

Y funciona como un encanto, pero me pregunto si es el camino para lograr Django soporte para múltiples perfiles diferentes que utilizan Django perfiles? Me preocupa que tenga que usar get() varias veces más antes de renderizar los detalles del perfil o editar el formulario.

Pero después de 4 días de lucha con Django para que esto se haga por fin puedo dormir bien esta noche :)

Saludos

Cuestiones relacionadas