2010-09-22 33 views
6

models.py của tôi:hồ sơ người dùng khác nhau với django-profiles & django đăng ký

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)                           

tôi sử dụng để lập bản đồ BaseProfile user_id để user_type cụ thể. Tôi muốn sử dụng ProxyProfile như proxy mà tải user_type tùy cấu hình để ModelForm như hình dưới đây

Nội dung forms.py tôi:

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

ProfileForm được cung cấp để django-profile sử dụng đoạn mã sau trong urls.py:

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

tôi cũng đặt trong settings.py:

AUTH_PROFILE_MODULE = 'main.ProxyProfile' 

Trong quá trình đăng ký người dùng, tất cả dữ liệu db được điền chính xác (có vẻ như mọi thứ đều OK). tôi ghi danh bằng hình thức truyền cho django-đăng ký:

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

từ 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     

Và đăng ký giai đoạn hoạt động OK.

Tôi gặp sự cố với trang chỉnh sửa/chi tiết tiểu sử. Hồ sơ của tôi được lọc trong mô hình ProxyProfile và được sử dụng làm FormModel trong ProfileForm không được hiển thị (Tôi không thể xem các trường cụ thể của hồ sơ không được hiển thị trên trang HTML) Có thể có một số cách khác (giống như cách Django :)) này (chọn và hiển thị mô hình hồ sơ tùy thuộc vào trường user_type có liên quan đến mô hình Người dùng).

Cảm ơn trước :)

+0

Tôi thấy bạn đã sử dụng một mô hình proxy. Bất kỳ lý do nào bạn không thể chỉ làm cho BaseProfile là một lớp cơ sở trừu tượng (xem http://docs.djangoproject.com/en/1.2/topics/db/models/#abstract-base-classes) để Django sẽ tải đúng subtype cho bạn? –

+0

Tôi đã sử dụng mô hình proxy dựa trên BaseProfile vì tôi muốn ghi đè phương thức get_profile từ lớp Người dùng. get_profile() được gọi bởi ứng dụng django-profiles để tìm nạp mô hình hồ sơ liên kết với người dùng. Vấn đề là tôi đã có các mô hình hồ sơ khác nhau cho những người dùng khác nhau (nhưng một người dùng <-> một loại tiểu sử). –

Trả lời

5

Ok, cuối cùng tôi đã có một ý tưởng làm thế nào tôi có thể làm điều này :)

Trong models.py tôi:

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

Trong quản lý tùy chỉnh - BaseManager Tôi trả về đối tượng hồ sơ bằng cách ghi đè phương thức get() được get_profile sử dụng. Tôi phải sử dụng UserManager được đặt tên đơn giản là 'manager' để ngăn chặn cuộc gọi đệ quy của người quản lý tùy chỉnh khi chỉ định self.bt

OK, đây là một nửa để đạt được những gì tôi muốn, bây giờ tôi có thể xem các hồ sơ khác nhau đính kèm với người dùng bằng django ứng dụng hồ sơ.

Tiếp theo, tôi muốn sử dụng ModelForm để chuẩn bị biểu mẫu chỉnh sửa cho hồ sơ người dùng. Người dùng có thể có cấu hình khác nhau vì vậy tôi đã áp dụng các trick ảo thuật được trình bày trong đoạn này: http://djangosnippets.org/snippets/2081/

Và bây giờ trong forms.py của tôi, tôi có:

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


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

tiếp theo, hình thức mô hình đơn giản cho mỗi hồ sơ được lắp ráp trong 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): 
     ... 

Trong cài đặt.py:

AUTH_PROFILE_MODULE = 'main.BaseProfile' 

Và nó hoạt động như một sự quyến rũ nhưng tôi tự hỏi nếu đó là cách Django để đạt được hỗ trợ cho nhiều cấu hình khác nhau bằng cách sử dụng tiểu sử django? Tôi lo lắng rằng tôi phải sử dụng get() vài lần trước khi tôi hiển thị chi tiết hồ sơ hoặc chỉnh sửa biểu mẫu.

Nhưng sau 4 ngày kể từ khi vật lộn với Django để thực hiện điều này cuối cùng tôi có thể ngủ ngon đêm nay :)

Cheers

Các vấn đề liên quan