Django DRF调用SerializerMethodField的answer方法缺失2个必填位置参数
DRF SerializerMethodField 缺参数报错修复
报错信息
TypeError: answer() missing 2 required positional arguments: 'Poll' and 'Answers'
问题根因
serializers.SerializerMethodField绑定的回调方法参数签名不符合DRF框架的调用规则:
- 序列化器中定义的实例方法,第一个固定参数必须是
self - 框架调用该方法时,只会传入1个业务参数:当前正在被序列化的模型实例,也就是当前序列化器
Meta.model指定的Poll类对应的数据行实例
原代码中answer方法除self之外额外声明了Options、Poll、Answers三个形参,框架调用时仅会传入当前Poll实例,剩余参数无对应传值,直接触发缺参报错。
除此之外原代码还存在几处写法问题:
- 混淆类型注解和函数参数语法:类型注解的写法是
参数名: 类型,不是把模型类直接写在参数列表里当形参 - 重复查库:方法入参拿到的就是当前Poll实例,不需要再调用
Poll.objects.get()重复查询当前对象 - 循环内重复执行count查询,存在不必要的性能开销
- 序列化器类名
pollSerializer小写开头,不符合Python类名大驼峰命名规范
修正后代码
from rest_framework import serializers from .models import Answers, Poll, Options from authUser.models import User class PollSerializer(serializers.ModelSerializer): class Meta: model = Poll fields = ["pollAnswer"] pollAnswer = serializers.SerializerMethodField(method_name="get_poll_answer") def get_poll_answer(self, obj: Poll): # obj为当前序列化的Poll实例,无需重复查库获取 poll_type = obj.pollType if poll_type == 0: return obj.pollAnswer if poll_type == 1: options = Options.objects.filter(pollId=obj.pk) max_vote = 0 target_option_id = 0 for option in options: vote_count = Answers.objects.filter(pollId=obj.pk, optionId=option.pk).count() if vote_count > max_vote: max_vote = vote_count target_option_id = option.pk return target_option_id
写法规范提醒
- 所有
SerializerMethodField绑定的方法,固定签名为def 方法名(self, 当前序列化实例),需要用到其他模型直接在方法内部调用查询即可,不需要写在参数列表里 - 类型注解仅做类型提示用,不会实际参与参数传递,不要把类型声明当成形参写
- 序列化单条数据时直接使用框架传入的实例对象即可,避免重复查库
内容的提问来源于stack exchange,提问作者mehdi_ahmadi
相关产品推荐
相关产品推荐

