我正在创建一个Django
后端,我使用Django Rest Framework
来构建REST API
。
我有嵌套序列化,当我尝试序列化数据时,我必须重写ModelSerializers的create函数。我有点害怕这会导致问题或后端安全漏洞,因为我在创建对象时没有使用默认验证。
那么这样做正常吗?
# THIS IS MY MODELS.PY
from django.db import models
from django.contrib.auth.models import User
class UnivStudent(models.Model):
"""
A class based model for storing the records of a university student
Note: A OneToOne relation is established for each student with User model.
"""
user = models.OneToOneField(User)
subject_major = models.CharField(name="subject_major", max_length=60)
# THIS IS MY SERIALIZERS.PY
from rest_framework import serializers, status
from models import *
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class StudentSerializer(serializers.ModelSerializer):
"""
A student serializer to return the student details
"""
user = UserSerializer(required=True)
class Meta:
model = UnivStudent
fields = ('user', 'subject_major',)
def create(self, validated_data):
"""
Overriding the default create method of the Model serializer.
:param validated_data: data containing all the details of student
:return: returns a successfully created student record
"""
user_data = validated_data.pop('user')
user = UserSerializer.create(UserSerializer(), validated_data=user_data)
student, created = UnivStudent.objects.update_or_create(user=user,
subject_major=validated_data.pop('subject_major'))
return student
最后,
# THIS IS MY VIEWS.PY
from serializers import *
from models import *
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class StudentRecordView(APIView):
"""
A class based view for creating and fetching student records
"""
def get(self, format=None):
"""
Get all the student records
:param format: Format of the student records to return to
:return: Returns a list of student records
"""
students = UnivStudent.objects.all()
serializer = StudentSerializer(students, many=True)
return Response(serializer.data)
def post(self, request):
"""
Create a student record
:param format: Format of the student records to return to
:param request: Request object for creating student
:return: Returns a student record
"""
serializer = StudentSerializer(data=request.data)
if serializer.is_valid(raise_exception=ValueError):
serializer.create(validated_data=request.data)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.error_messages,
status=status.HTTP_400_BAD_REQUEST)
做如下修改:与原框架相同
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class StudentSerializer(serializers.ModelSerializer):
"""
A student serializer to return the student details
"""
user = UserSerializer(required=True)
class Meta:
model = UnivStudent
fields = ('user', 'subject_major',)
def create(self, validated_data):
"""
Overriding the default create method of the Model serializer.
:param validated_data: data containing all the details of student
:return: returns a successfully created student record
"""
user_data = validated_data.pop('user')
original_user_data = self.initial_data.get('user')
user_serializer = UserSerializer(data=original_user_data)
user_serializer.is_valid(raise_exception=True)
user = user_serializer.save()
# user = UserSerializer.create(UserSerializer(), validated_data=user_data)
validated_data['user'] = user
return super(StudentSerializer, self).create(validated_data)
# student, created = UnivStudent.objects.update_or_create(user=user,
# subject_major=validated_data.pop('subject_major'))
# return student
和视图
class StudentRecordView(APIView):
"""
A class based view for creating and fetching student records
"""
def get(self, format=None):
"""
Get all the student records
:param format: Format of the student records to return to
:return: Returns a list of student records
"""
students = UnivStudent.objects.all()
serializer = StudentSerializer(students, many=True)
return Response(serializer.data)
def post(self, request):
"""
Create a student record
:param format: Format of the student records to return to
:param request: Request object for creating student
:return: Returns a student record
"""
serializer = StudentSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
这是一个不好的方式,你应该引用PrimaryKeyRelatedField和SerializerMethodField来重新构造你的序列化器。我相信你可以在序列化器中解决嵌套的序列化器问题,不需要在视图中自定义。