Django-Registration & Django-Profile,使用你自己的自定义表单
Posted
技术标签:
【中文标题】Django-Registration & Django-Profile,使用你自己的自定义表单【英文标题】:Django-Registration & Django-Profile, using your own custom form 【发布时间】:2011-02-05 18:53:12 【问题描述】:我正在使用 django-registration 和 django-profile 来处理注册和配置文件。我想在注册时为用户创建个人资料。我创建了一个自定义注册表单,并使用以下教程将其添加到 urls.py:
http://dewful.com/?p=70
教程中的基本思想是覆盖默认注册表单以同时创建配置文件。
forms.py - 在我的个人资料应用中
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from profiles.models import UserProfile
from registration.models import RegistrationProfile
attrs_dict = 'class': 'required'
class UserRegistrationForm(RegistrationForm):
city = forms.CharField(widget=forms.TextInput(attrs=attrs_dict))
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_profile = UserProfile(user=new_user, city=self.cleaned_data['city'])
new_profile.save()
return new_user
在 urls.py 中
from profiles.forms import UserRegistrationForm
和
url(r'^register/$',
register,
'backend': 'registration.backends.default.DefaultBackend', 'form_class' : UserRegistrationForm,
name='registration_register'),
显示表格,我可以在城市中输入,但它不会在数据库中保存或创建条目。
【问题讨论】:
Solution with signals - 这里我写了如何使用信号来保存额外的数据 【参考方案1】:您已经成功了——您已经成功构建了一个替换默认表单的自定义表单。但是您正在尝试使用模型表单上的 save() 方法进行自定义处理。这在旧版本的 django-registration 中是可能的,但我可以从您在 URL conf 中指定后端的事实中看出,您使用的是 v0.8。
upgrade guide 说:
以前,用于收集的表单 注册期间的数据是预期的 实现一个 save() 方法 将创建新的用户帐户。 这已不再是这种情况;创造 该帐户由后端处理, 所以任何自定义逻辑都应该是 移动到自定义后端,或通过 将侦听器连接到信号 在注册过程中发送。
换句话说,现在您使用的是 0.8 版,表单上的 save() 方法将被忽略。您需要使用自定义后端或信号进行自定义处理。我选择创建一个自定义后端(如果有人使用信号进行此操作,请发布代码 - 我无法让它以这种方式工作)。您应该能够修改它以保存到您的自定义配置文件中。
-
在您的应用中创建一个 regbackend.py。
将 DefaultBackend 中的 register() 方法复制到其中。
在方法结束时,进行查询以获取对应的 User 实例。
将其他表单字段保存到该实例中。
修改 URL conf 使其同时指向自定义表单和自定义后端
所以 URL conf 是:
url(r'^accounts/register/$',
register,
'backend': 'accounts.regbackend.RegBackend','form_class':MM_RegistrationForm,
name='registration_register'
),
regbackend.py 具有必要的导入,基本上是 DefaultBackend 的副本,只有 register() 方法,并添加了:
u = User.objects.get(username=new_user.username)
u.first_name = kwargs['first_name']
u.last_name = kwargs['last_name']
u.save()
【讨论】:
感谢您的评论。决定在注册时进行重定向以创建个人资料,这样您就没有未激活用户的个人资料。但是会将此问题标记为已回答。 新版djando注册也有同样的问题。 Shacker,但具体在哪里:“将 register() 方法从 DefaultBackend 复制到其中。” DefaultBackend??,在哪里?谢谢 Asinox - 您需要从 django-registration 源代码中获取它。查看registration/backends/default/__init__.py 这很棒。我做到了,但我的用户仍然无法从表单中获取 first_name 和 last_name。【参考方案2】:如my comment on Django Trac ticket 中所述,我创建了一个元类和mixin 以允许ModelForm
Django 表单的多重继承。有了这个,您可以简单地制作一个表单,该表单允许同时注册来自用户和配置文件模型的字段,而无需硬编码字段或重复自己。通过使用我的元类和 mixin(以及 fieldset mixin),您可以:
class UserRegistrationForm(metaforms.FieldsetFormMixin, metaforms.ParentsIncludedModelFormMixin, UserCreationForm, UserProfileChangeForm):
error_css_class = 'error'
required_css_class = 'required'
fieldset = UserCreationForm.fieldset + [(
utils_text.capfirst(UserProfileChangeForm.Meta.model._meta.verbose_name),
'fields': UserProfileChangeForm.base_fields.keys(),
)]
def save(self, commit=True):
# We disable save method as registration backend module should take care of user and user
# profile objects creation and we do not use this form for changing data
assert False
return None
__metaclass__ = metaforms.ParentsIncludedModelFormMetaclass
其中UserCreationForm
可以是例如django.contrib.auth.forms.UserCreationForm
形式和UserProfileChangeForm
一个简单的ModelForm
用于您的配置文件模型。 (不要忘记在 User
模型的外键中将 editable
设置为 False
。)
django-registration 后端有这样的注册方法:
def register(self, request, **kwargs):
user = super(ProfileBackend, self).register(request, **kwargs)
profile, created = utils.get_profile_model().objects.get_or_create(user=user)
# lambda-object to the rescue
form = lambda: None
form.cleaned_data = kwargs
# First name, last name and e-mail address are stored in user object
forms_models.construct_instance(form, user)
user.save()
# Other fields are stored in user profile object
forms_models.construct_instance(form, profile)
profile.save()
return user
注意注册信号是在这个方法的开头(在超类的方法中)而不是在结尾发送的。
以同样的方式,您可以为用户和个人资料信息制作更改表单。您可以在我对上面提到的 Django Trac 票证的评论中找到这方面的示例。
【讨论】:
我最近用信号实现了同样的东西,但这真是太棒了!我绝对需要学习如何使用元类和混合技术! 你可以看到here的一个使用例子。【参考方案3】:注册 0.8 及更高版本:
在您的views.py 或等效文件中创建registration.backends.default.views.RegistrationView 的子类:
from registration.backends.default.views import RegistrationView
class MyRegistrationView(RegistrationView):
form_class= MyCustomRegistrationForm
def register(self, request, **cleaned_data):
new_user= super(MyRegistrationView, self).register(request, **cleaned_data)
# here create your new UserProfile object
return new_user
【讨论】:
以上是关于Django-Registration & Django-Profile,使用你自己的自定义表单的主要内容,如果未能解决你的问题,请参考以下文章
django-registration 与 paypal 集成