Django 1.5のカスタムユーザーモデルとdjango-registration その3
以下の続き
Django 1.5のカスタムユーザーモデルとdjango-registration - brainstorm
Django 1.5のカスタムユーザーモデルとdjango-registration その2 - brainstorm
Django 1.5のカスタムユーザーモデルを使っていて、fork版のdjango-registrationでユーザー登録できるだろうか
eire1130 / django-registration ― Bitbucket
登録処理の入り口であるviews.registerを見ると、backendやform_classはカスタマイズ可能になっている
def register(request, backend, success_url=None, form_class=None, disallowed_url='registration_disallowed', template_name='registration/registration_form.html', extra_context=None):
formを指定しないとデフォルトのRegistrationFormが表示されるので、カスタムユーザーモデルがusername、emailを持ってない場合などは自作する必要がある。
今回はemailをusernameとして使ってるのでこんな感じにしてみた。
try: from django.contrib.auth import get_user_model except ImportError: # django < 1.5 from django.contrib.auth.models import User else: User = get_user_model() from django import forms from django.utils.translation import ugettext_lazy as _ attrs_dict = {'class': 'required'} class MyRegistrationForm(forms.Form): email = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=75)), label=_("E-mail")) email_confirm = forms.EmailField(widget=forms.TextInput(attrs=dict(attrs_dict, maxlength=75)), label=_("E-mail(again)")) password1 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False), label=_("Password")) password2 = forms.CharField(widget=forms.PasswordInput(attrs=attrs_dict, render_value=False), label=_("Password (again)")) def clean_email(self): existing = User.objects.filter(email__iexact=self.cleaned_data['email']) if existing.exists(): raise forms.ValidationError(_("A user with that email already exists.")) return self.cleaned_data['email'] def clean(self): print "clean" if 'password1' in self.cleaned_data and 'password2' in self.cleaned_data: if self.cleaned_data['password1'] != self.cleaned_data['password2']: raise forms.ValidationError(_("The two password fields didn't match.")) if 'email' in self.cleaned_data and 'email_confirm' in self.cleaned_data: if self.cleaned_data['email'] != self.cleaned_data['email_confirm']: raise forms.ValidationError(_("The two email fields didn't match.")) return self.cleaned_data
views.register関数はフォームの入力値がvalidであれば、backendのregister関数を呼び出す
デフォルトで用意されているDefaultBackendのregister関数はこんな感じ
def register(self, request, **kwargs): username, email, password = kwargs['username'], kwargs['email'], kwargs['password1'] if Site._meta.installed: site = Site.objects.get_current() else: site = RequestSite(request) new_user = RegistrationProfile.objects.create_inactive_user(username, email, password, site) signals.user_registered.send(sender=self.__class__, user=new_user, request=request) return new_user
みてみると、フォームからusernameという入力値が渡ってくることが前提になっている。ここはカスタムのバックエンドを作成して修正する必要がある。
さらにRegistrationProfileManagerのcreate_inactive_userもusername、email、passwordを受け取る仕様になっている
create_inactive_userの中身をみると、User(カスタムユーザーモデル)のManagerのcreate_userをを呼び出していて、ここでも引数が固定になっている
def create_inactive_user(self, username, email, password, site, send_email=True): new_user = User.objects.create_user(username, email, password) new_user.is_active = False new_user.save() registration_profile = self.create_profile(new_user) if send_email: registration_profile.send_activation_email(site) return new_user
create_userとcreate_superuserはカスタムユーザーモデルを作成する場合は、自分で定義しなおすことになっているので、ここが固定だと対応できない。
ここまで見てもういいやって感じになってしまったんだけど、今回のようにusernameを持たないカスタムユーザーモデルを使う場合、django-registrationは(fork版でも)使えない。
backendやRegistrationProfileなど部分部分をカスタマイズしまくれば対応できると思うけど、
そこまでするのであれば、最初からregistrationに依存せず、自前でロジック組んだほうがよさそう。