djangoのログインフォームで「ログイン情報を保持」の有無を選択できるようにする

django標準のログインフォーム(確かAuthenticationForm)ではブラウザをとじたあともログイン状態を保持するかを選択できません。実際のサイト構築ではこの機能が必須になってくるかと思います。

スコトプリゴニエフスク通信さんを参考にしました。
pinaxというdjangoをベースにしたフレームワーク?のコードが引用されています。

私の場合、ログインにusernameを使わず、emailで行っているので強引に工夫します(usernameはプレースホルダが書きこまれています)

forms.py

class LoginForm(forms.Form):
    email = forms.EmailField(label=_("Email"), max_length=30)
    password = forms.CharField(label=_("Password"), widget=forms.PasswordInput(render_value=False))
    remember = forms.BooleanField(label=_("Remember Me"), help_text=_("If checked you will stay logged in for 3 weeks"), required=False)

    user = None

    def clean(self):
        if self._errors:
            return
        
        try:
            u = User.objects.get(email=self.cleaned_data["email"])
        except User.DoesNotExist:
            raise forms.ValidationError(_("The username and/or password you specified are not correct."))
        
        user = authenticate(username=u.username, password=self.cleaned_data["password"])
        if user:
            if user.is_active:
                self.user = user
            else:
                raise forms.ValidationError(_("This account is currently inactive."))
        else:
            raise forms.ValidationError(_("The username and/or password you specified are not correct."))
        return self.cleaned_data

    def login(self, request):
        if self.is_valid():
            login(request, self.user)
#            request.user.message_set.create(message=_(u"Successfully logged in as %(username)s.") % {'username': self.user.username})
            if self.cleaned_data['remember']:
                request.session.set_expiry(60 * 60 * 24 * 7 * 3)
            else:
                request.session.set_expiry(0)
            return True
        return False

views.py

def login(request):
    if request.user.is_authenticated():
        # すでにログイン済み
    
    if request.method == 'POST':
        form = LoginForm(data=request.POST)
        if form.is_valid():
            if form.login(request):
                # ログイン成功
            else:
                # ログイン失敗
    else:
        form = LoginForm()

    return render_to_response('accounts/index.html', {
        'form': form,
    })

簡単ですね。formのclean()はview側でis_valid()を呼ばないと実行されないので注意。