【问题标题】:Different user profiles with django-profiles & django-registration使用 django-profiles 和 django-registration 的不同用户配置文件
【发布时间】:2011-04-15 21:54:03
【问题描述】:

我的models.py:

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)                                                                                                         

我使用 BaseProfile 将 user_id 映射到特定的 user_type。我想使用 ProxyProfile 作为代理,它将依赖于用户类型的配置文件加载到 ModelForm,如下所示

我的 forms.py 的内容:

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

ProfileForm 使用 urls.py 中的以下代码提供给 django-profiles:

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

我在settings.py中也设置了:

AUTH_PROFILE_MODULE = 'main.ProxyProfile'

在用户注册期间,所有数据库数据均已正确填写(看起来一切正常)。 我使用传递给 django-registration 的表单进行注册:

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

来自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                

注册阶段工作正常。

我的个人资料编辑/详细信息页面有问题。 我的配置文件在 ProxyProfile 模型中过滤并用作 ProfileForm 中的 FormModel 未呈现(我看不到配置文件特定字段未呈现到 HTML 页面) 也许还有其他方式(更像是 Django 方式:))来做到这一点 (根据与用户模型相关的 user_type 字段选择和渲染配置文件模型)。

提前致谢:)

【问题讨论】:

  • 我看到您使用了代理模型。有什么理由不能让 BaseProfile 成为抽象基类(请参阅docs.djangoproject.com/en/1.2/topics/db/models/…)以便 Django 为您加载正确的子类型?
  • 我使用了基于 BaseProfile 的代理模型,因为我想覆盖 User 类的 get_profile 方法。 django-profiles 应用程序调用 get_profile() 以获取与用户关联的配置文件模型。问题是我对不同的用户有不同的配置文件模型(但一个用户 一种配置文件类型)。

标签: user-interface django-registration django-profiles


【解决方案1】:

好的,我终于知道该怎么做了:)

在我的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) 
    ...

在自定义管理器 - BaseManager 中,我通过覆盖 get_profile 使用的 get() 方法返回配置文件对象。在分配 self.bt 时,我必须使用简单命名为“manager”的 UserManager 来防止自定义管理器的递归调用

好的,这是实现我想要的一半的方法,现在我可以使用 django-profiles 应用查看附加到用户的不同配置文件。

接下来,我想使用 ModelForm 为用户配置文件准备编辑表单。用户可以有不同的配置文件,所以我应用了这个 sn-p 中介绍的魔术技巧:http://djangosnippets.org/snippets/2081/

现在在我的 forms.py 中有:

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


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

接下来,在 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):
        ...

在settings.py中:

AUTH_PROFILE_MODULE = 'main.BaseProfile'

它就像一个魅力,但我想知道它是否是 Django 使用 django-profiles 实现对多个不同配置文件的支持的方式? 让我担心的是,在呈现个人资料详细信息或编辑表单之前,我必须再使用几次 get()。

但是经过 4 天与 Django 的努力完成这项工作后,我今晚终于可以睡个好觉了 :)

干杯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-15
    • 2013-07-12
    • 2011-06-04
    • 2013-05-21
    • 2012-11-19
    • 2011-12-23
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多