【发布时间】:2020-12-19 06:51:33
【问题描述】:
我正在使用 DjangoRestFramework 和 ReactJS 开发一个测验应用程序。我的应用由两个应用组成,api 和 frontend。在我的 api 应用程序中,我有多个 API 视图用于许多不同的事情。我的 API 视图之一称为 JoinQuiz。当我在 frontend 上调用它时,我在控制台中收到此错误:
Forbidden: /api/join-quiz
[16/Dec/2020] "POST /api/join-quiz HTTP/1.1" 403 58
我不认为我的问题是由于 CSRF 错误,因为我的其他 API 视图工作正常。在这一点上我可能错了。
[16/Dec/2020] "GET /api/get-question?id=3 HTTP/1.1" 200 10009
[17/Dec/2020 01:15:47] "POST /api/create-quiz HTTP/1.1" 201 11959
我怀疑我的request.session 可能是问题,因为当我直接转到/api/join-quiz 并使用我的code 发出POST 请求时,没有任何问题,并且我的帖子成功了。
文件
Views.py
class QuizView(generics.ListAPIView):
queryset = Quiz.objects.all()
serializer_class = QuizSerializer
class GetQuiz(APIView):
""" Searches for a quiz given its code and returns the Quiz with is_host info"""
serializer_class = QuizSerializer
lookup_url_kwarg = 'code'
def get(self, request, format=None): # This is an HTTP GET request
code = request.GET.get(self.lookup_url_kwarg)
if code != None: # Check if code is not equal to None
quiz = Quiz.objects.filter(code=code)
if len(quiz) > 0: # If there is a quiz...
data = QuizSerializer(quiz[0]).data
data['is_host'] = self.request.session.session_key == quiz[0].host
return Response(data, status=status.HTTP_200_OK)
return Response({'Quiz not found': 'Invalid Code'}, status=status.HTTP_404_NOT_FOUND)
return Response({'Bad Request': 'Code Parameter not found in request'}, status=status.HTTP_400_BAD_REQUEST)
class CreateQuizView(APIView):
"""Creates A new Quiz given nested question and answer data"""
serializer_class = QuizSerializer
def post(self, request, format=None):
""" Create the User's Account first"""
if not self.request.session.exists(self.request.session.session_key):
self.request.session.create()
data = request.data
data['host'] = self.request.session.session_key
serializer = self.serializer_class(data=data)
if serializer.is_valid():
quiz = serializer.create(validated_data=data)
self.request.session['quiz_code'] = quiz.code
return Response(
self.serializer_class(quiz).data,
status=status.HTTP_201_CREATED
)
return Response({'Bad Request': 'Invalid Data'}, status=status.HTTP_400_BAD_REQUEST)
class JoinQuiz(APIView):
"""Join a quiz based on the quiz code"""
lookup_url_kwarg = 'code'
def post(self, request, format=None):
if not self.request.session.exists(self.request.session.session_key):
self.request.session.create()
print(self.request.session.session_key)
code = request.data.get(self.lookup_url_kwarg)
if code != None:
quiz_result = Quiz.objects.filter(code=code)
if len(quiz_result) > 0:
self.request.session['quiz_code'] = code
return Response({'message': 'Quiz Joined!'}, status=status.HTTP_200_OK)
return Response({'Quiz Not Found': 'Invalid Quiz Code'}, status=status.HTTP_404_NOT_FOUND)
return Response({'Bad Request': 'Invalid Post Data'}, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class QuizSerializer(serializers.ModelSerializer):
questions = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Quiz
fields = ['id', 'code', 'questions', 'name']
def create(self, validated_data):
questions_data = validated_data.pop('questions')
quiz = Quiz.objects.create(**validated_data)
for question_data in questions_data:
answers_data = question_data.pop('answers')
question = Question.objects.create(quiz=quiz, **question_data)
for answer_data in answers_data:
Answer.objects.create(question=question, **answer_data)
return quiz
前端请求
const quizButtonPressed = () => {
const requestOptions = {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
code: quizCode
})
};
fetch('/api/join-quiz', requestOptions)
.then((response) => {
if (response.ok) {
props.history.push(`/play/${quizCode}`);
} else {
setError("Quiz not found")
}
})
.catch((error) => console.log(error));
}
编辑
我遵循了@Blusky 的解决方案,它奏效了!
按照@Blusky 的 Django 文档链接解决了问题:https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax
【问题讨论】:
标签: python reactjs django post django-rest-framework