2010-09-22 10 views
6

Mein models.py:Verschiedene Benutzerprofile mit django-Profile & django-Registrierung

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)                           

Ich benutze BaseProfile auf bestimmte user_type abzubilden User_id. Ich wollte ProxyProfile als Proxy verwenden, die user_type je Profile Modelform lädt wie unten

Inhalt meiner forms.py gezeigt:

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

ProfileForm vorgesehen ist, um django-Profile folgenden Code in urls.py mit:

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

ich auch in settings.py festgelegt haben:

AUTH_PROFILE_MODULE = 'main.ProxyProfile' 

Während der Benutzerregistrierung werden alle Datenbankdaten korrekt ausgefüllt (es sieht so aus, als ob alles in Ordnung ist). I-Register mit Formular-Registrierung django geben:

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

von 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     

Und Registrierungsphase funktioniert OK.

Ich habe ein Problem mit Profil bearbeiten/Details Seiten. Meine Profile im ProxyProfile-Modell gefiltert und als FormModel in ProfileForm verwendet werden nicht gerendert (ich kann nicht sehen, profilspezifische Felder werden nicht auf HTML-Seite gerendert) Vielleicht gibt es einen anderen Weg (mehr wie Django Weg :)) zu tun dies (Profilmodell auswählen und rendern abhängig von user_type Feld, das mit Benutzermodell verwandt ist).

Vielen Dank im Voraus :)

+0

Ich sehe Sie ein Proxy-Modell verwendet haben. Jeder Grund, warum Sie BaseProfile nicht einfach zu einer abstrakten Basisklasse machen können (siehe http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes), damit Django das Recht lädt Subtyp für Sie? –

+0

Ich habe das Proxy-Modell basierend auf BaseProfile verwendet, weil ich die get_profile-Methode aus der User-Klasse überschreiben möchte. get_profile() wird von der App django-profiles aufgerufen, um das mit dem Benutzer verknüpfte Profilmodell abzurufen. Das Problem ist, dass ich verschiedene Profilmodelle für verschiedene Benutzer habe (aber einen Benutzer <-> einen Profiltyp). –

Antwort

5

Ok, schließlich habe ich eine Idee hatte, wie ich dies tun

In meinem 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) 
    ... 

In benutzerdefinierten Manager - BaseManager I gibt ein Profilobjekt zurück, indem die von get_profile verwendete Methode get() überschrieben wird. Ich muss UserManager genannt einfach 'Manager' verwenden, um rekursiven Aufruf des benutzerdefinierten Managers zu verhindern, wenn es self.bt

OK, dies ist ein halber Weg zu achive, was ich will, jetzt kann ich verschiedene Profile an Benutzer mit django angeschlossen anzeigen -Profile App.

Als nächstes möchte ich ModelForm verwenden, um das Bearbeitungsformular für Benutzerprofile vorzubereiten. Benutzer können unterschiedliche Profile haben, damit ich die magischen Trick in diesem Snippet präsentiert angewendet haben: http://djangosnippets.org/snippets/2081/

Und jetzt in meinem forms.py ich habe:

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


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

nächsten, einfaches Modell Formen für jedes Profil zusammengebaut werden in 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): 
     ... 

in Einstellungen.py: mit django-Profile

AUTH_PROFILE_MODULE = 'main.BaseProfile' 

Und es wirkt wie ein Zauber, aber ich frage mich, ob es die Django Weg ist die Unterstützung für mehrere unterschiedliche Profile zu erreichen? Es macht mir Sorgen, dass ich get() noch ein paar Mal verwenden muss, bevor ich Profildetails rendere oder das Formular bearbeite.

Aber nach 4 Tagen mit Django kämpft dies endlich erledigen kann ich heute Nacht gut schlafen :)

Prost

Verwandte Themen