前回からの続きになります。汎用viewを使用しないで自作のカスタムでログインフォームを作り、更に自作のカスタムでパスワード変更フォームを作成した場合に、django内部のシステムにより強制ログアウトをされてしまいます。
今回はそんな強制ログアウトも含めてformで効果的なバリデーションを持たせて、どのようなコードを書けば良いのかを具体的にコードで紹介していきます。
コンテンツ
環境
環境は以下になります。ちなみにヒロヤンの場合はpipenvでの環境開発を行っています。
・OS Mac
・python 3.8
・djano 2.2
実際のコード
実際にどのようなコードを書いていきます。
想定されるケースは以下のような画面です。
前提条件として既にログイン状態を想定します。
views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
from django.views.decorators.http import require_http_methods from django.contrib.auth imort authenticate, login from django.core.urlresolvers import reverse from.forms import EditProfilePasswordForm @require_http_methods(['GET', 'POST']) def edit_profile_password(request): user = User.objects.get(id=request.user.id) if request.method != 'POST': form = EditProfilePasswordForm(user.username) else: form = EditProfilePasswordForm(user.username, request.POST) if form.is_valid(): password = form.cleaned_data['confirm_new_password'] user.set_password(password) user.save() user = authenticate(username=request.user, password=password) login(request, user) return HttpResponseRedirect(reverse('アプリ名:urlsのnameで指定したリダイレクト先')) |
解説をします。
- 8行目でログイン中のユーザーをuserとして変数定義しておきます。
- 11行目以降はpost時になります。
- formが有効ならば14行目以下に進みます。このformの詳しい内容は以降のforms.pyで説明します。
- 15行目で入力されたパスワードをハッシュ化しています。
- 16行目でsave()と同時に内部的にログアウトされました。
- 17行目で認証を行います。
- 18行目で内部的にログインを実行します。
- 19行目でパスワード変更が終了したのパスワード変更成功のページにリダイレクトを実行します。
forms.py
今回紹介するフォームでは、ユーザー認証はユーザー名とパスワードで実行するため、viewsの12行目でEditProfilePasswordFormの第一引数にuser.usernameを渡しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
from django import forms from django.core.exceptions import ValidationError from django.contrib.auth import authenticate class EditProfilePasswordForm(forms.Form): current_password = forms.CharField( required=True, max_length=255, min_length=6, widget=forms.PasswordInput( ) ) new_password = forms.CharField( required=True, max_length=255, min_length=6, widget=forms.PasswordInput( ) ) confirm_new_password = forms.CharField( required=True, max_length=255, min_length=6, widget=forms.PasswordInput( ) ) def __init__(self, _user_name, *args, **kwargs): super().__init__(*args, **kwargs) self._user_name = _user_name def clean(self): cleaned_data = super(EditProfilePasswordForm, self).clean() print(cleaned_data) return cleaned_data def clean_current_password(self): current_password = self.cleaned_data['current_password'] if self._user_name and current_password: auth_result = authenticate( username = self._user_name, password=current_password ) if not auth_result: raise ValidationError('Password is incorrect') return current_password def clean_new_password(self): new_password = self.cleaned_data['new_password'] return new_password def clean_confirm_new_password(self): confirm_new_password = self.cleaned_data['confirm_new_password'] if confirm_new_password != self.cleaned_data['new_password']: raise ValidationError('Passwords do not match') return confirm_new_password |
こちらのコードは認証のために、views側からusernameを渡されており、それを41行目の認証で使用しています。そのための処理が、__init__での処理になります。
基本的には小難しいことはしていませんが、djangoの便利な汎用viewを使用しないできちんとゼロからformを組み立てるとこのようなコードになるかと思います。
あとは各々で、追加したいパスワード条件を記載をしていけばうまくいくはずです。
スクールを利用して本格的に学ぶ
いかがでしたでしょうか?
10人中9人が挫折すると言われるプログラミングを、ヒロヤンも実はプログラミングスクールで学習をしてきたからで、結果、今はPythonエンジニアとして働いています。
挫折率が高いプログラミングこそお金を払ってメンターを付けて、道を見失わないように環境を構築する必要があるのではないでしょうか。
これはダイエットで自分一人では痩せられないけど、トレーナーを付けて否が応でもせざるを得ない環境を作ると一緒ですね。
ヒロヤンもプログラミング勉強開始直後はあれこれ悩みましたが、悩むよりも手っ取り早くスクールに登録した方が最短ルートで勉強できるのではないかと考え、結果挫折せずに今に至っています。
今なら無料でキャリアカウンセリングを行っているCodeCamp(コードキャンプ)のようなプログラミングスクールもありますのでこれを機会に是非カウンセリングだけでも受けてみてはいかがでしょうか?
上記リンク先から無料相談ができます。
またこちら(↓)ではPython専用のプログラミングスクールをまとめ紹介しています。
コメントを残す