如何判断用户的电子邮件地址是否已使用 Django、allauth、rest-auth 和自定义用户进行验证
How to tell if user's email address has been verified using Django, allauth, rest-auth and a custom user
我正在将 Django 2.0.10 与 rest-framework、rest-auth 和 allauth 一起使用。我有一个自定义用户模型。
我已经使用 allauth 视图进行了电子邮件验证。验证电子邮件在用户注册时发送。如果我点击电子邮件中的 link,我将被带到一个页面,其中有一个按钮可以单击以验证电子邮件。这一切都没有错误。但是,我无法弄清楚这实际上 做了什么 。用户数据中的任何字段似乎都没有改变。
我想要的行为是让用户能够注册和登录,但只有在他们验证了他们的电子邮件后才能向网站添加内容。
编辑:this post给出了部分答案,但没有说如何将验证状态保存为用户的属性,以便您在前端查看加载用户数据。
settings.py
# django rest auth
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
OLD_PASSWORD_FIELD_ENABLED = True
LOGOUT_ON_PASSWORD_CHANGE = False
ACCOUNT_EMAIL_VERIFICATION = 'optional'
api/urls.py
from allauth.account.views import confirm_email
urlpatterns = [
re_path(r'^rest-auth/registration/account-confirm-email/(?P<key>[-:\w]+)/$', confirm_email,
name='account_confirm_email'),
...
]
users/models.py
import uuid
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
from django.utils.http import int_to_base36
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
ID_LENGTH = 12
def pkgen():
from base64 import b32encode
from hashlib import sha1
from random import random
pk = int_to_base36(uuid.uuid4().int)[:ID_LENGTH]
return pk
class CustomUser(AbstractUser):
objects = CustomUserManager()
slug = models.CharField(max_length=ID_LENGTH, default=pkgen, editable=False)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
def __str__(self):
return self.email
当用户登录时,我如何知道他们是否已经验证了他们的电子邮件地址?感谢您的帮助!
啊哈!感谢this post and this post,我想我有答案了
电子邮件地址的状态保存在单独的 table EmailAdress 中,而不是用户模型的一部分。这可以在模型视图集中访问,如下所示:
api.py
from allauth.account.admin import EmailAddress
class ListViewSet(viewsets.ModelViewSet):
...
def get_queryset(self):
# can view public lists and lists the user created
if self.request.user.is_authenticated:
print('is there a verified email address?')
print(EmailAddress.objects.filter(user=self.request.user, verified=True).exists())
...
如果用户有任何经过验证的电子邮件地址,这将 return 为真。
但是,为用户添加验证状态更有用。这可以通过 here.
解释的信号来完成
views.py
from allauth.account.signals import email_confirmed
from django.dispatch import receiver
@receiver(email_confirmed)
def email_confirmed_(request, email_address, **kwargs):
user = email_address.user
user.email_verified = True
user.save()
现在 api.py 您可以这样检查:
print(self.request.user.email_verified)
如果您只有一个无法更改或删除的电子邮件地址,则此方法有效。如果您允许多个电子邮件地址,我想您需要进行更多检查并相应地更新用户状态。但是我只有一个用于登录的电子邮件地址,所以我认为可以。
我认为将 'email_verified' 作为用户个人资料的一部分是更好的做法,但这是一个有效的演示。
我遇到了同样的问题,我使用下面的代码解决了这个问题:
#Project-level folder urls.py
from django.contrib import admin
from django.urls import path, include
from allauth.account.views import ConfirmEmailView, EmailVerificationSentView
#These ConfirmEmailView, EmailVerificationSentView are very important
#I used other allauth/ dj-rest-auth views and they didn't automatically verify the email.
urlpatterns = [
path('admin/', admin.site.urls),
path('dj-rest-auth/registration/account-confirm-email/<str:key>/',
ConfirmEmailView.as_view()), #This is at the top because apparently won't work if below. #Integral to problem solution
path('dj-rest-auth/', include('dj_rest_auth.urls')),
path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
path('api-auth', include('rest_framework.urls')),
path('dj-rest-auth/registration/account-confirm-email/',
EmailVerificationSentView.as_view(),
name='account_email_verification_sent'),#Integral to problem solution
]
上面的代码允许我通过注册 url 创建新用户。之后会发送一封带有 link 的电子邮件。当用户单击 link 时,他们将被重定向到登录页面,他们的电子邮件现已在数据库中得到验证。
官方示例:
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
fields = '__all__'
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
我正在将 Django 2.0.10 与 rest-framework、rest-auth 和 allauth 一起使用。我有一个自定义用户模型。
我已经使用 allauth 视图进行了电子邮件验证。验证电子邮件在用户注册时发送。如果我点击电子邮件中的 link,我将被带到一个页面,其中有一个按钮可以单击以验证电子邮件。这一切都没有错误。但是,我无法弄清楚这实际上 做了什么 。用户数据中的任何字段似乎都没有改变。
我想要的行为是让用户能够注册和登录,但只有在他们验证了他们的电子邮件后才能向网站添加内容。
编辑:this post给出了部分答案,但没有说如何将验证状态保存为用户的属性,以便您在前端查看加载用户数据。
settings.py
# django rest auth
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
OLD_PASSWORD_FIELD_ENABLED = True
LOGOUT_ON_PASSWORD_CHANGE = False
ACCOUNT_EMAIL_VERIFICATION = 'optional'
api/urls.py
from allauth.account.views import confirm_email
urlpatterns = [
re_path(r'^rest-auth/registration/account-confirm-email/(?P<key>[-:\w]+)/$', confirm_email,
name='account_confirm_email'),
...
]
users/models.py
import uuid
from django.contrib.auth.models import AbstractUser, UserManager
from django.db import models
from django.utils.http import int_to_base36
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
ID_LENGTH = 12
def pkgen():
from base64 import b32encode
from hashlib import sha1
from random import random
pk = int_to_base36(uuid.uuid4().int)[:ID_LENGTH]
return pk
class CustomUser(AbstractUser):
objects = CustomUserManager()
slug = models.CharField(max_length=ID_LENGTH, default=pkgen, editable=False)
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
def __str__(self):
return self.email
当用户登录时,我如何知道他们是否已经验证了他们的电子邮件地址?感谢您的帮助!
啊哈!感谢this post and this post,我想我有答案了
电子邮件地址的状态保存在单独的 table EmailAdress 中,而不是用户模型的一部分。这可以在模型视图集中访问,如下所示:
api.py
from allauth.account.admin import EmailAddress
class ListViewSet(viewsets.ModelViewSet):
...
def get_queryset(self):
# can view public lists and lists the user created
if self.request.user.is_authenticated:
print('is there a verified email address?')
print(EmailAddress.objects.filter(user=self.request.user, verified=True).exists())
...
如果用户有任何经过验证的电子邮件地址,这将 return 为真。
但是,为用户添加验证状态更有用。这可以通过 here.
解释的信号来完成views.py
from allauth.account.signals import email_confirmed
from django.dispatch import receiver
@receiver(email_confirmed)
def email_confirmed_(request, email_address, **kwargs):
user = email_address.user
user.email_verified = True
user.save()
现在 api.py 您可以这样检查:
print(self.request.user.email_verified)
如果您只有一个无法更改或删除的电子邮件地址,则此方法有效。如果您允许多个电子邮件地址,我想您需要进行更多检查并相应地更新用户状态。但是我只有一个用于登录的电子邮件地址,所以我认为可以。
我认为将 'email_verified' 作为用户个人资料的一部分是更好的做法,但这是一个有效的演示。
我遇到了同样的问题,我使用下面的代码解决了这个问题:
#Project-level folder urls.py
from django.contrib import admin
from django.urls import path, include
from allauth.account.views import ConfirmEmailView, EmailVerificationSentView
#These ConfirmEmailView, EmailVerificationSentView are very important
#I used other allauth/ dj-rest-auth views and they didn't automatically verify the email.
urlpatterns = [
path('admin/', admin.site.urls),
path('dj-rest-auth/registration/account-confirm-email/<str:key>/',
ConfirmEmailView.as_view()), #This is at the top because apparently won't work if below. #Integral to problem solution
path('dj-rest-auth/', include('dj_rest_auth.urls')),
path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
path('api-auth', include('rest_framework.urls')),
path('dj-rest-auth/registration/account-confirm-email/',
EmailVerificationSentView.as_view(),
name='account_email_verification_sent'),#Integral to problem solution
]
上面的代码允许我通过注册 url 创建新用户。之后会发送一封带有 link 的电子邮件。当用户单击 link 时,他们将被重定向到登录页面,他们的电子邮件现已在数据库中得到验证。
官方示例:
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
fields = '__all__'
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days