Ign*_*icz 6 user-interface django-profiles django-registration
我的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)
Run Code Online (Sandbox Code Playgroud)
我使用BaseProfile将user_id映射到特定的user_type.我想使用ProxyProfile作为代理,它将user_type依赖的配置文件加载到ModelForm,如下所示
我的forms.py的内容:
class ProfileForm(ModelForm):
...
class Meta:
model = ProxyProfile
exclude = ('user','user_type')
...
Run Code Online (Sandbox Code Playgroud)
使用urls.py中的以下代码向django-profiles提供ProfileForm:
urlpatterns += patterns('',
url(r'^profiles/edit/', edit_profile,
{'form_class': ProfileForm},
name='profiles_edit_profile'),
(r'^profiles/',include('profiles.urls')),
)
Run Code Online (Sandbox Code Playgroud)
我还设置了settings.py:
AUTH_PROFILE_MODULE = 'main.ProxyProfile'
Run Code Online (Sandbox Code Playgroud)
在用户注册期间,所有数据库数据都正确填充(看起来一切正常).我使用传递给django-registration的表单注册:
urlpatterns += patterns('',
url(r'^register/$', register,
{'form_class': UserRegistrationForm},
name='registration.views.register'),
(r'', include('registration.urls')),
)
Run Code Online (Sandbox Code Playgroud)
来自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
Run Code Online (Sandbox Code Playgroud)
注册阶段工作正常.
我对个人资料编辑/详情页面有疑问.我在ProxyFrofile模型中过滤并在ProfileForm中用作FormModel的配置文件未呈现(我看不到配置文件特定字段未呈现到HTML页面)也许有其他方式(更像是Django方式:))来做这个(选择并根据与用户模型相关的user_type字段呈现配置文件模型.
提前致谢 :)
好的,最后我已经知道如何做到这一点:)
在我的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)
...
Run Code Online (Sandbox Code Playgroud)
在自定义管理器 - BaseManager中,我通过覆盖get_profile使用的get()方法返回profile对象.我必须使用名为'manager'的UserManager来防止在分配self.bt时自定义管理器的递归调用
好的,这是实现我想要的一半,现在我可以使用django-profiles app查看附加到用户的不同配置文件.
接下来,我想使用ModelForm为用户配置文件准备编辑表单.用户可以使用不同的配置文件,因此我应用了此代码段中提供的魔术技巧:http://djangosnippets.org/snippets/2081/
现在在我的forms.py中,我有:
class FreeForm(forms.ModelForm):
class Meta:
model = FreeProfile
class PremiumForm(forms.ModelForm):
class Meta:
model = PremiumProfile
Run Code Online (Sandbox Code Playgroud)
接下来,在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):
...
Run Code Online (Sandbox Code Playgroud)
在settings.py中:
AUTH_PROFILE_MODULE = 'main.BaseProfile'
Run Code Online (Sandbox Code Playgroud)
它就像一个魅力,但我想知道是否是使用django-profiles获得支持多个不同配置文件的Django方式?令我担心的是,在渲染配置文件详细信息或编辑表单之前,我必须多次使用get().
但经过4天的努力与Django完成这项工作后,我今晚可以睡得很好:)
干杯
| 归档时间: |
|
| 查看次数: |
2244 次 |
| 最近记录: |