使用Django rest框架注册电子邮件验证

使用Django rest框架注册电子邮件验证,django,authentication,django-rest-framework,django-authentication,django-rest-auth,Django,Authentication,Django Rest Framework,Django Authentication,Django Rest Auth,我通过android应用程序发送POST请求来创建一个用户,该请求包含用户名、密码和电子邮件id。现在在我的应用程序中,有两种用户,即教师和学生。现在,为了在注册过程中区分教师和学生,我想向教师发送一封验证电子邮件,其中包含一个随机生成的令牌。现在我想让老师在注册过程中输入这个令牌,以验证实际上是一个老师注册了,而不是一个只想和每个人捣乱的淘气学生我可以发送包含令牌的电子邮件,但无法理解当教师在注册时在应用程序上输入令牌时,如何验证该令牌与发送到电子邮件id的令牌匹配。 下面是用于发送包含令牌的

我通过android应用程序发送POST请求来创建一个用户,该请求包含用户名、密码和电子邮件id。现在在我的应用程序中,有两种用户,即教师学生。现在,为了在注册过程中区分教师和学生,我想向教师发送一封验证电子邮件,其中包含一个随机生成的令牌。现在我想让老师在注册过程中输入这个令牌,以验证实际上是一个老师注册了,而不是一个只想和每个人捣乱的淘气学生我可以发送包含令牌的电子邮件,但无法理解当教师在注册时在应用程序上输入令牌时,如何验证该令牌与发送到电子邮件id的令牌匹配。

下面是用于发送包含令牌的电子邮件的序列化程序的代码

class UserSerializer(serializers.ModelSerializer):
    token = serializers.CharField(max_length=100, null=True, blank=True)

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'email', 'token')

    def create(self, validated_data):
        user = User(username=validated_data['username'], 
        email=validated_data['email'])
        user.set_password(validated_data['password'])
        user.save()

        subject = "Email verification for django"
        message = account_activation_token.make_token(user)
        send_mail(subject, message, settings.EMAIL_HOST_USER, 
        [user.email])
        return user
正如您所见,在上面的代码中,我生成了一个随机令牌,并在收到创建新用户的POST请求时发送电子邮件。现在,我的用户将在应用程序的电子邮件中输入令牌并发送POST请求。现在我想检查用户输入的令牌是否与上面代码中生成的令牌相同,以便验证用户并继续执行注册表单

PS:我的用户模型不包含令牌字段,因为我正在使用Django提供的内置用户模型,并使用一对一字段将其连接到教师模型


PPS:我是否可以使用其他方法来实现上述功能?

您需要将令牌保存在您的一侧(数据库),以便与教师输入到表单中的令牌相匹配。所以先做一个模型

class Token(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    token = models.CharField(max_length=255)
生成令牌的行出现在用户创建之后,因此您可以使用用户实例并将令牌保存到刚才创建的模型上:

def create(self, validated_data):
    ...
    message = account_activation_token.make_token(user)
    Token.objects.create(user=user, token=message)
    send_mail(subject, message, settings.EMAIL_HOST_USER,
    ...
接下来,在视图中使用以下代码检查用户是否输入了正确的令牌:

...
token_obj = Token.objects.get(user=user)
user_token = token_obj.token
if form.data['token'] == user_token:
    # code to accept the user
    token_obj.delete() # this deletes the row since you will not use it anymore
else:
    # code to reject the user

注意:请不要复制粘贴这些代码。相应地进行调整。

我宁愿使用
def validate.*
其中*可以是任何字段(用于字段级验证),如中所述:


谢谢你的回答。我认为这对我来说可能非常有效,但是如果它能够更加健壮,因为最终您将从数据库中删除令牌,因为它只是用于验证。还有,许多大公司是如何从android应用程序注册的?如果不删除代币,我想他们的注册不会有问题。但是,您可以在验证完成后添加代码以从数据库中删除该行。我不太清楚大公司是如何做到这一点的,因为我不是一名应用程序开发人员,也从未与DRF合作过。我已更新答案中的代码以删除该行。如果我的回答对你有帮助,请投票并接受。谢谢。:)
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

from .models import SomeModel


class SomeModelSerializer(ModelSerializer):
    class Meta:
        model = SomeModel
        fields = (
            "email",
            "password",
        )

    def create(self, validated_data):
        user = SomeModel.objects.create_user(**validated_data)
        return user

    def validate_email(self, email):
        try:
            validate_email(email)
        except ValidationError:
            raise serializers.ValidationError('email is invalid')    
        return email