2010-09-22 16 views
6

Moja models.py:różne profile użytkowników z Django profile i django rejestracji

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)                           

używam BaseProfile mapować user_id do konkretnego user_type. Chciałem użyć ProxyProfile jako serwer proxy, który ładuje user_type zależności profile do ModelForm jak pokazano poniżej

Treści mojego forms.py:

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

ProfileForm jest przewidziany do Django profili za pomocą następującego kodu w urls.py:

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

mam ustawione również w settings.py:

AUTH_PROFILE_MODULE = 'main.ProxyProfile' 

Podczas rejestracji użytkownika wszystkie dane bazy danych są wypełnione poprawnie (wygląda na to, że wszystko jest w porządku). zarejestrować za pomocą formularza przekazanego do Django rejestracji:

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

z 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     

i rejestracji faza działa OK.

Mam problem z edycją profilu/stronami szczegółów. Moje profile filtrowane w ProxyProfile i używane jako FormModel w ProfileForm nie są renderowane (nie widzę pól specyficznych dla profilu nie są renderowane do strony HTML) Może jest jakiś inny sposób (bardziej jak sposób Django :)) do zrobienia to (wybierz i wyrenderuj model profilu w zależności od pola user_type, które jest powiązane z modelem User).

góry dzięki :)

+0

Widzę, że używany model proxy. Każdy powód, dla którego nie można po prostu uczynić BaseProfile abstrakcyjną klasą podstawową (zobacz http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes), aby Django ładował poprawnie podtyp dla ciebie? –

+0

Użyłem modelu proxy opartego na BaseProfile, ponieważ chciałbym nadpisać metodę get_profile z klasy User. Funkcja get_profile() jest wywoływana przez aplikację django-profiles w celu pobrania modelu profilu powiązanego z użytkownikiem. Problem polega na tym, że mam różne modele profili dla różnych użytkowników (ale jeden użytkownik ma jeden typ profilu). –

Odpowiedz

5

Ok, wreszcie miałem pomysł jak mogę to zrobić :)

W moim 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) 
    ... 

W niestandardowego menedżera - BaseManager Zwracam obiekt profilu przez nadpisanie metody get() używanej przez get_profile. Muszę użyć menedżera UserManager nazwanego po prostu 'managerem', aby zapobiec rekursywnemu wywołaniu niestandardowego menedżera podczas przypisywania self.bt

OK, to jest połowa drogi do osiągnięcia tego, co chcę, teraz mogę zobaczyć różne profile dołączone do użytkowników za pomocą django -profile app.

Następnie chcę użyć ModelForm do przygotowania formularza edycji dla profili użytkowników. Użytkownicy mogą mieć różne profile więc już zastosował sztuczkę magiczną przedstawione w tym fragmencie: http://djangosnippets.org/snippets/2081/

a teraz w moim forms.py mam:

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


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

obok, proste formy modelowe dla każdego profilu są montowane w ProfilForm:

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): 
     ... 

W ustawieniach.py:

AUTH_PROFILE_MODULE = 'main.BaseProfile' 

i działa jak czar, ale zastanawiam się, czy jest to droga Django osiągnąć wsparcie dla wielu różnych profili z wykorzystaniem profili Django? Martwi mnie, że muszę użyć get() kilka razy zanim wyrenderuję szczegóły profilu lub edytuję formularz.

Ale po 4 dni zmaga się z Django, aby to zrobić w końcu mogę dobrze spać tej nocy :)

Cheers

Powiązane problemy