python django {' user':[errordetail(string ='不正确类型。期望的pk value,接收到boundfield。
我正在Django上发展后端。我在注册视图类中编写了用于用户注册的代码,以前效果很好。我不得不将电子邮件确认合并到其中,这也可以单独使用。但是,完成所有操作后,我添加了一些条件以确保工作正常,但是我得到了“ string ='不正确的类型。预期的pk value,接收到了boundfield。”和“ forbidden:/pibi/v1.0/user /register-patient/“错误。
另外,要澄清工作流程。注册时,每个用户都会为JWT令牌分配。该令牌与发送给电子邮件的代币不同。我将后者命名为“ verification_token”。
因此,用户签名,他们的“ IS_ACTIVE”字段设置为false,直到他们单击电子邮件中收到的链接为止。 SendGrid电子邮件API用于发送电子邮件。仅当DEBERE_SERIALIZER数据存储在数据库中时,该电子邮件才会发送。
当用户单击通过电子邮件接收到的链接时,他们的“ IS_ACTIVE”字段将设置为true,现在可以登录。
此外,实际的SendGrid API密钥是代码的一部分,我在此处将其删除。
我的models.py文件:
from django.db import models
from django.contrib.auth.models import User
class VerificatonToken(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='token')
verification_token = models.CharField(
max_length=256, blank=True, null=True)
我的serializer.py文件:
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueValidator
from rest_framework_jwt.settings import api_settings
from .models import VerificatonToken
class TokenSerializer(serializers.ModelSerializer):
class Meta:
model = VerificatonToken
fields = ('user', 'verification_token',)
class PatientSerializer(serializers.ModelSerializer):
token = serializers.SerializerMethodField()
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
username = serializers.CharField(
required=True,
max_length=32,
validators=[UniqueValidator(queryset=User.objects.all())]
)
first_name = serializers.CharField(
required=True,
max_length=32
)
last_name = serializers.CharField(
required=True,
max_length=32
)
# DOB = serializers.DateField(
# required=True
# )
# gender = serializers.CharField(
# required=True
# )
# address = serializers.CharField(
# required=True,
# max_length=60
# )
# contactNo = serializers.IntegerField(
# required=True,
# max_length=11
# )
password = serializers.CharField(
required=True,
min_length=8,
write_only=True
)
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
def get_token(self, obj):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(obj)
token = jwt_encode_handler(payload)
return token
class Meta:
model = User
fields = (
'token',
'username',
'password',
'first_name',
'last_name',
'email',
'is_active',
# 'DOB',
# 'address',
# 'contactNo',
'id'
)
我的views.py文件:
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import PatientSerializer, TokenSerializer
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
import uuid
import hashlib
from .models import VerificatonToken
from rest_framework.permissions import AllowAny
class TestView(APIView):
def get(self, request, format=None):
print("API called")
return Response("You did it!", status=200)
# Registering User & Sending Email Confirmation
class RegisterView(APIView):
permission_classes = [AllowAny]
def post(self, request, format=None):
print("Registering User")
user_data = request.data
user_data['is_active'] = False
print(request.data)
patient_serializer = PatientSerializer(data=user_data)
if patient_serializer.is_valid(raise_exception=False):
patient_serializer.save()
salt = uuid.uuid4().hex
hash_object = hashlib.sha256(
salt.encode() + str(patient_serializer.data['id']).encode())
verification_token = hash_object.hexdigest() + ':' + salt
verification_token_serializer = TokenSerializer(
data={'user': patient_serializer['id'], 'token': verification_token})
if verification_token_serializer.is_valid(raise_exception=False):
verification_token_serializer.save()
message = Mail(
from_email='[email protected]',
to_emails=user_data['email'],
subject='Please Confirm Your Email Address',
html_content=f"Hi {user_data['username']}!\
<br><br>\
Welcome to All-in-one Health App. To finish signing up, please click \
<a href='http://localhost:8000/api/v1.0/user/verify-patient/{verification_token}'>HERE</a>\
")
try:
sg = SendGridAPIClient(
'<Sendgrid API KEY>')
response = sg.send(message)
print(response)
return Response(patient_serializer.data, status=200)
except Exception as e:
print('ERROR', e)
else:
print(patient_serializer.errors,
verification_token_serializer.errors)
return Response({'msg': 'error'}, status=403)
# RegisterPatientView() provides customized link to VerifyPatientView() in email to patient
# compares the token provided to verify the email
class PatientVerificationView(APIView):
def get(self, request, pk, format=None):
print("Verifying Patient", pk)
tokenObj = VerificatonToken.objects.filter(token=pk).first()
user = User.objects.filter(id=tokenObj.user.id).first()
if user:
patient_serializer = PatientSerializer(
user, data={'is_active': True})
if patient_serializer.is_valid(raise_exception=False):
patient_serializer.save()
return Response('Patient email verified', status=200)
return Response(status=404)
class PatientLoginView(APIView):
# convert user token to user data
def get(self, request, format=None):
if request.user.is_authenticated == False or request.user.is_active == False:
return Response('Invalid credentials', status=403)
user = PatientSerializer(request.user)
print(user.data)
return Response("Testing", status=200)
# authenticate user data
def post(self, request, format=None):
print("Login class")
# Looking for user's email or username
user_obj = User.objects.filter(email=request.data['username']).first(
) or User.objects.filter(username=request.data['username']).first()
# if user is valid, returns user data in credentials
if user_obj is not None:
credentials = {
'username': user_obj.username,
'password': request.data['password']
}
user = authenticate(**credentials)
# if user is valid and active, logs user in
if user and user.is_active:
user_serializer = PatientSerializer(user)
print("Login successful")
return Response(user_serializer.data, status=200)
return Response("Invalid credentials", status=403)
邮递员请求:
命令行:
Tokenserializer基本上是给出错误的。 patiet_serializer工作正常,因为用户信息将“ In_Active”字段设置为false进入数据库。我不知道如何修复它。
I'm developing my backend on Django. I wrote a code for user registration under RegistrationView class, and it worked fine before. I had to incorporate email confirmation in it, which also worked fine on its own. However, after all of that was done, I added some conditions to ensure proper working, but I get the "string='Incorrect type. Expected pk value, received BoundField.'" and "Forbidden: /api/v1.0/user/register-patient/" error.
Also, to clarify the workflow. Each user is assigned a JWT token while signing up. This token is different from the token sent to verify email. I named the latter "verification_token".
So a user signs up, their 'is_active' field is set to False until they click on the link received in their email. Sendgrid email API was used to send the email. The email is only sent if the patient_serializer data is stored in the db.
When the user clicks on the link received through email, their 'is_active' field is set to True, and they can now log in.
Also, the actual sendgrid API key is a part of the code, I removed it here.
My models.py file:
from django.db import models
from django.contrib.auth.models import User
class VerificatonToken(models.Model):
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='token')
verification_token = models.CharField(
max_length=256, blank=True, null=True)
My serializers.py file:
from rest_framework import serializers
from django.contrib.auth.models import User
from rest_framework.validators import UniqueValidator
from rest_framework_jwt.settings import api_settings
from .models import VerificatonToken
class TokenSerializer(serializers.ModelSerializer):
class Meta:
model = VerificatonToken
fields = ('user', 'verification_token',)
class PatientSerializer(serializers.ModelSerializer):
token = serializers.SerializerMethodField()
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
username = serializers.CharField(
required=True,
max_length=32,
validators=[UniqueValidator(queryset=User.objects.all())]
)
first_name = serializers.CharField(
required=True,
max_length=32
)
last_name = serializers.CharField(
required=True,
max_length=32
)
# DOB = serializers.DateField(
# required=True
# )
# gender = serializers.CharField(
# required=True
# )
# address = serializers.CharField(
# required=True,
# max_length=60
# )
# contactNo = serializers.IntegerField(
# required=True,
# max_length=11
# )
password = serializers.CharField(
required=True,
min_length=8,
write_only=True
)
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
def get_token(self, obj):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(obj)
token = jwt_encode_handler(payload)
return token
class Meta:
model = User
fields = (
'token',
'username',
'password',
'first_name',
'last_name',
'email',
'is_active',
# 'DOB',
# 'address',
# 'contactNo',
'id'
)
My views.py file:
from rest_framework.views import APIView
from rest_framework.response import Response
from .serializers import PatientSerializer, TokenSerializer
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
import uuid
import hashlib
from .models import VerificatonToken
from rest_framework.permissions import AllowAny
class TestView(APIView):
def get(self, request, format=None):
print("API called")
return Response("You did it!", status=200)
# Registering User & Sending Email Confirmation
class RegisterView(APIView):
permission_classes = [AllowAny]
def post(self, request, format=None):
print("Registering User")
user_data = request.data
user_data['is_active'] = False
print(request.data)
patient_serializer = PatientSerializer(data=user_data)
if patient_serializer.is_valid(raise_exception=False):
patient_serializer.save()
salt = uuid.uuid4().hex
hash_object = hashlib.sha256(
salt.encode() + str(patient_serializer.data['id']).encode())
verification_token = hash_object.hexdigest() + ':' + salt
verification_token_serializer = TokenSerializer(
data={'user': patient_serializer['id'], 'token': verification_token})
if verification_token_serializer.is_valid(raise_exception=False):
verification_token_serializer.save()
message = Mail(
from_email='[email protected]',
to_emails=user_data['email'],
subject='Please Confirm Your Email Address',
html_content=f"Hi {user_data['username']}!\
<br><br>\
Welcome to All-in-one Health App. To finish signing up, please click \
<a href='http://localhost:8000/api/v1.0/user/verify-patient/{verification_token}'>HERE</a>\
")
try:
sg = SendGridAPIClient(
'<Sendgrid API KEY>')
response = sg.send(message)
print(response)
return Response(patient_serializer.data, status=200)
except Exception as e:
print('ERROR', e)
else:
print(patient_serializer.errors,
verification_token_serializer.errors)
return Response({'msg': 'error'}, status=403)
# RegisterPatientView() provides customized link to VerifyPatientView() in email to patient
# compares the token provided to verify the email
class PatientVerificationView(APIView):
def get(self, request, pk, format=None):
print("Verifying Patient", pk)
tokenObj = VerificatonToken.objects.filter(token=pk).first()
user = User.objects.filter(id=tokenObj.user.id).first()
if user:
patient_serializer = PatientSerializer(
user, data={'is_active': True})
if patient_serializer.is_valid(raise_exception=False):
patient_serializer.save()
return Response('Patient email verified', status=200)
return Response(status=404)
class PatientLoginView(APIView):
# convert user token to user data
def get(self, request, format=None):
if request.user.is_authenticated == False or request.user.is_active == False:
return Response('Invalid credentials', status=403)
user = PatientSerializer(request.user)
print(user.data)
return Response("Testing", status=200)
# authenticate user data
def post(self, request, format=None):
print("Login class")
# Looking for user's email or username
user_obj = User.objects.filter(email=request.data['username']).first(
) or User.objects.filter(username=request.data['username']).first()
# if user is valid, returns user data in credentials
if user_obj is not None:
credentials = {
'username': user_obj.username,
'password': request.data['password']
}
user = authenticate(**credentials)
# if user is valid and active, logs user in
if user and user.is_active:
user_serializer = PatientSerializer(user)
print("Login successful")
return Response(user_serializer.data, status=200)
return Response("Invalid credentials", status=403)
Postman request:
Command line:
EDIT: My TokenSerializer is basically the one giving an error. The Patiet_Serializer is working fine because the user info goes into the database with the 'in_active' field set to false. I can't figure out how to fix it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论