如何为含多对多字段的DRF序列化器编写适配Vue+Axios的create()函数
问题原因
你现有代码的核心问题有3个:
- 序列化器中无法直接通过
self.request获取请求对象,需要从DRF传入的上下文context中提取 - 从查询参数拿到的
class_id是主键值,直接传入add()方法虽然支持传主键,但如果对应班级不存在会直接抛出异常,缺少校验 - 序列化器字段声明中包含了
classes字段,但前端提交表单时没有传递该字段,会触发字段必填校验错误
正确实现代码
首先修改序列化器,注意提前导入from django.shortcuts import get_object_or_404:
class StudentSerializer(serializers.ModelSerializer): # 把classes字段设为只读,避免前端提交时要求传值 classes = serializers.PrimaryKeyRelatedField(many=True, read_only=True) class Meta: model = Student fields = ( "id", "classes", "studentID", "lastName", "firstName", "gender", "dob", "ssn", "tel", "address", "email", "userName", "acctPass", "note" ) def create(self, validated_data): # 从序列化器上下文获取请求对象 request = self.context['request'] # 提取班级ID并查询对应班级实例,不存在时直接返回404错误 clss_id = request.query_params.get('class_id') clss = get_object_or_404(Class, pk=clss_id) # 创建学生实例 student = Student.objects.create(**validated_data) # 绑定多对多关联,不需要额外调用student.save() student.classes.add(clss) return student
如果你的Django版本支持直接传主键到add()方法,也可以跳过查询直接写student.classes.add(clss_id),但推荐先查询做存在性校验。
可选优化(视图集兼容)
你现有的视图集get_queryset方法强制要求所有请求都带class_id参数,会导致不需要该参数的请求报错,可修改为仅传参时过滤:
class StudentViewSet(viewsets.ModelViewSet): serializer_class = StudentSerializer queryset = Student.objects.all() def get_queryset(self): queryset = super().get_queryset() clssID = self.request.query_params.get('class_id') if clssID: clss = get_object_or_404(Class, pk=clssID) queryset = queryset.filter(classes=clss) return queryset
内容的提问来源于stack exchange,提问作者shinhwa
相关产品推荐
相关产品推荐

