前提・実現したいこと
DjangoでWebサイトの会員登録機能を作成しようとしています。
コードの参考に以下のサイトを参考にさせていただいています。
https://blog.narito.ninja/detail/38/
実現したいことは、
①会員登録ページからメールアドレス、パスワードを入力する。
②送信ボタンを押すとユーザー情報を保存し、仮登録完了メールを送信する。
③届いたメールに添付されたURLをクリックする。
④開かれたURLのなかで、追加の会員情報として名字、名前、会社名、住所を入力する。
⑤完了ボタンを押して、ユーザー情報を保存し、本登録完了ページへ移行する。
という流れの実装です。
しかし⑥で以下のエラーメッセージが発生しました。
メールアドレス、パスワードを登録した上で、追加で名字、名前、会社名、住所を登録したいと考えているのですが、下記エラーが出てしまいます。解決策を教えていただければ幸いです。
初心者マークをつけ忘れたので一度更新しました。
発生している問題・エラーメッセージ
IntegrityError at user_create/detail/Mze:1k3uvF:CJK6fjLLY4xYk0CaUt1K2qFZqJM/ UNIQUE constraint failed: app_user.email
該当のソースコード
formspy
1class UserCreateForm(UserCreationForm): 2 """ユーザー仮登録用フォーム""" 3 4 class Meta: 5 model = User 6 fields = ('email',) 7 8 def __init__(self, *args, **kwargs): 9 super().__init__(*args, **kwargs) 10 for field in self.fields.values(): 11 field.widget.attrs['class'] = 'form-control' 12 13 def clean_email(self): 14 email = self.cleaned_data['email'] 15 User.objects.filter(email=email, is_active=False).delete() 16 return email 17 18class UserAddForm(forms.ModelForm): 19 """ユーザー本登録用フォーム""" 20 21 class Meta: 22 model = User 23 fields = ('first_name','last_name','company','address',) 24 25 def __init__(self, *args, **kwargs): 26 super().__init__(*args, **kwargs) 27 for field in self.fields.values(): 28 field.widget.attrs['class'] = 'form-control'
viewspy
1class UserCreateDetail(generic.CreateView): 2 """メール内URLアクセス後のユーザー本登録""" 3 model = User 4 form_class = UserAddForm 5 template_name = 'app/user_create_detail.html' 6 timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60*60*24) 7 8 def get(self, request, **kwargs): 9 """tokenが正しければ仮登録の情報保存.""" 10 token = kwargs.get('token') 11 try: 12 user_pk = loads(token, max_age=self.timeout_seconds) 13 14 # 期限切れ 15 except SignatureExpired: 16 return HttpResponseBadRequest() 17 18 # tokenが間違っている 19 except BadSignature: 20 return HttpResponseBadRequest() 21 22 # tokenは問題なし 23 else: 24 try: 25 user = User.objects.get(pk=user_pk) 26 except User.DoesNotExist: 27 return HttpResponseBadRequest() 28 else: 29 if not user.is_active: 30 # 問題なければ仮登録の情報保存(本登録はマダ) 31 user.is_active = False 32 user.save() 33 return super().get(request, **kwargs) 34 35 return HttpResponseBadRequest() 36 37 def get_success_url(self): 38 return resolve_url('app:user_create_complete', pk=self.kwargs['pk']) 39 40class UserCreateComplete(generic.TemplateView): 41 """ユーザー本登録""" 42 template_name = 'app/user_create_complete.html' 43 timeout_seconds = getattr(settings, 'ACTIVATION_TIMEOUT_SECONDS', 60*60*24) # デフォルトでは1日以内 44 45 def get(self, request, **kwargs): 46 """tokenが正しければ本登録.""" 47 token = kwargs.get('token') 48 try: 49 user_pk = loads(token, max_age=self.timeout_seconds) 50 51 # 期限切れ 52 except SignatureExpired: 53 return HttpResponseBadRequest() 54 55 # tokenが間違っている 56 except BadSignature: 57 return HttpResponseBadRequest() 58 59 # tokenは問題なし 60 else: 61 try: 62 user = User.objects.get(pk=user_pk) 63 except User.DoesNotExist: 64 return HttpResponseBadRequest() 65 else: 66 if not user.is_active: 67 # 問題なければ本登録とする 68 user.is_active = True 69 user.save() 70 return super().get(request, **kwargs) 71 72 return HttpResponseBadRequest()
modelpy
1class User(AbstractBaseUser, PermissionsMixin): 2 """カスタムユーザーモデル.""" 3 4 email = models.EmailField(_('メールアドレス'), unique=True) 5 first_name = models.CharField(_('first name'), max_length=30, blank=True) 6 last_name = models.CharField(_('last name'), max_length=150, blank=True) 7 company = models.CharField(_('会社名'), max_length=150, blank=True) 8 address = models.CharField(_('住所'), max_length=150, blank=True) 9 10 is_staff = models.BooleanField( 11 _('staff status'), 12 default=False, 13 help_text=_( 14 'Designates whether the user can log into this admin site.'), 15 ) 16 is_active = models.BooleanField( 17 _('active'), 18 default=True, 19 help_text=_( 20 'Designates whether this user should be treated as active. ' 21 'Unselect this instead of deleting accounts.' 22 ), 23 ) 24 date_joined = models.DateTimeField(_('date joined'), default=timezone.now) 25 26 objects = CustomUserManager() 27 last_login = models.DateTimeField(_('last_login'), default=timezone.now) 28 EMAIL_FIELD = 'email' 29 USERNAME_FIELD = 'email' 30 REQUIRED_FIELDS = [] 31 32 class Meta: 33 verbose_name = _('user') 34 verbose_name_plural = _('users') 35 36 def get_full_name(self): 37 """Return the first_name plus the last_name, with a space in 38 between.""" 39 full_name = '%s %s' % (self.first_name, self.last_name) 40 return full_name.strip() 41 42 def get_short_name(self): 43 """Return the short name for the user.""" 44 return self.first_name 45 46 def email_user(self, subject, message, from_email=None, **kwargs): 47 """Send an email to this user.""" 48 send_mail(subject, message, from_email, [self.email], **kwargs) 49 50 @property 51 def username(self): 52 """username属性のゲッター 53 54 他アプリケーションが、username属性にアクセスした場合に備えて定義 55 メールアドレスを返す 56 """ 57 return self.email
urlspy
1from django.contrib import admin 2from django.urls import path,include 3from . import views 4 5app_name = 'app' 6urlpatterns = [ 7~ 省略~ 8 path('user_create/detail/<token>/', views.UserCreateDetail.as_view(), name='user_create_detail'), 9 path('user_create/complete/<int:pk>/', views.UserCreateComplete.as_view(), name='user_create_complete'), 10]
試したこと
class UserCreateDetail(generic.CreateView):にある def get_success_url(self):の中身に、
user = form.save(commit=False)
user.is_active = False
user.save()
など、ユーザー情報を保存するための方法を色々試しました。
あなたの回答
tips
プレビュー