2019/03/30

Djangoで自前のformでデフォルトのパスワードvalidationをする方法.

Djangoで自前のformでデフォルトのパスワードvalidationをする方法.

訳あって,Userモデルを拡張したモデル(UserPrivate)に対して,ModelFormではなく自前のformでユーザの追加をしたくなった.
普通にformを作ってみると,デフォルトのパスワードvalidationが有効にならない.

下記のようにすることで,settingsのAUTH_PASSWORD_VALIDATORSに登録されたvalidatoionを実行してくれる.
usernameとpasswordしか入力させないフォームなので,self.instance.usernameしか代入していないが,firstnameとかemailとかも場合によっては必要になる.

本当はもっとうまい方法がありそうなものだけど,よくわからん.
知っている人がいたら教えてほしい.



from django.contrib.auth.password_validation import validate_password


class UserPrivateAddForm(forms.ModelForm):
    """アカウント追加フォーム"""
    username = forms.CharField(
        label='ユーザID',
        required=True,
    )
    password = forms.CharField(
        label='パスワード',
        widget=forms.PasswordInput,
        help_text='パスワードを入力してください.'
    )
   
    def clean_password(self):
        # パスワードのvalidation時に username と似た値を禁止するUserAttributeSimilarityValidatorを機能させるためにusernameを代入
        password = self.cleaned_data.get('password')
        self.instance.username = self.cleaned_data.get('username')  # usernameを代入
        validate_password(
            self.cleaned_data['password'],
            self.instance  # ここでusernameの入ったインスタンスを渡す必要がある
        )  # デフォルトのパスワードvalidation
        return password
   
    def save(self, commit=True):
        user_private = super().save(commit=False)
        user_private.set_password(self.cleaned_data["password"])
        if commit:
            user_private.save()
        return user_private
   
    class Meta:
        model = UserPrivate
        fields = [
            'username',
            'password',
        ]