Django-Registration& Django-Profile,使用您自己的自定义表单

时间:2010-04-08 16:05:31

标签: python django django-forms registration profile

我正在使用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'),

显示表单,我可以在City中输入,但不会在DB中保存或创建条目。

3 个答案:

答案 0 :(得分:29)

你已经到了一半 - 你已经成功构建了一个替换默认表单的自定义表单。但是您尝试在模型表单上使用save()方法进行自定义处理。这在旧版本的django-registration中是可能的,但我可以从你在URL conf中指定后端使用v0.8的事实中看到。

upgrade guide说:

  

以前,用于收集的表格   预计登记期间的数据   实现一个save()方法   将创建新的用户帐户。   这已不再是这种情况;创建   该帐户由后端处理,   所以任何自定义逻辑都应该是   移动到自定义后端,或通过   将听众连接到信号   在注册过程中发送。

换句话说,当你使用版本0.8时,表单上的save()方法将被忽略。您需要使用自定义后端或信号进行自定义处理。我选择创建一个自定义后端(如果有人使用信号,请发布代码 - 我无法以这种方式工作)。您应该可以修改此项以保存到自定义配置文件。

  1. 在您的应用中创建regbackend.py。
  2. 将DefaultBackend中的register()方法复制到其中。
  3. 在方法结束时,执行查询以获取相应的用户实例。
  4. 将其他表单字段保存到该实例中。
  5. 修改URL conf,使其指向自定义表单和自定义后端
  6. 所以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() 
    

答案 1 :(得分:11)

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。 (不要忘记将外键中的editable设置为FalseUser模型。)

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票证的评论中找到此示例。

答案 2 :(得分:1)

注册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