我有两个序列化程序,第一个(稍微简化):
class FilterSerializer(serializers.Serializer):
brand = serializers.PrimaryKeyRelatedField(
queryset=org_models.Brand.objects, many=False,
error_messages={'does_not_exist': org_consts.BRAND_NOT_EXIST}
)
country = serializers.PrimaryKeyRelatedField(
queryset=org_models.Country.objects, many=False,
error_messages={'does_not_exist': org_consts.COUNTRY_NOT_EXIST}
)
level = serializers.PrimaryKeyRelatedField(
queryset=org_models.Level.objects, many=False, required=False,
error_messages={'does_not_exist': org_consts.DISTRICT_NOT_EXIST}
)
class Meta:
fields = ('brand', 'country', 'level')
和第二:
class PeopleReportSerializer(serializers.Serializer):
filters = FilterSerializer(many=True)
start_date = serializers.DateField(required=False)
end_date = serializers.DateField(required=False)
class Meta:
fields = ('filters', 'start_date', 'end_date')
def validate(self, data):
"""Check if end_date occurs after start_date.
"""
if data.get('start_date') and data.get('end_date'):
if data['start_date'] > data['end_date']:
raise serializers.ValidationError(constants.INVALID_START_DATE)
return data
为清楚起见,我删除了一些字段。 因此,如果数据库中存在具有已发布ID的对象,那么基本上我想从此序列化程序进行验证。在GET上我希望它根据request.user返回一些数据,但这是另一种情况。
所以现在在我看来我正在做这样的事情:
class PeopleReportView(ReportsPermissionMixin, views.APIView):
serializer_class = PeopleReportSerializer
task = staticmethod(people_report) # celery task, creates reports
def get(self, request):
# TODO: depending on request.user return initial data such as:
# country / brand / district and so on
return Response()
def post(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid(raise_exception=True):
task = self.task.apply_async(kwargs=serializer.data)
return Response({'task_id': task.id})
我的问题是,当我发布没有level
字段的数据(这不是必填字段)时,我得到KeyError: 'level'
。 显然我错了,我的测试没有测试FilterSerializer
工作正常,但是当它嵌套时我得到了这个错误。data
属性,只有is_valid
方法。
答案 0 :(得分:0)
请尝试使用allow_null
标志:
level = serializers.PrimaryKeyRelatedField(
queryset=org_models.Level.objects, many=False, allow_null=True,
error_messages={'does_not_exist': org_consts.DISTRICT_NOT_EXIST}
)
而不是:
level = serializers.PrimaryKeyRelatedField(
queryset=org_models.Level.objects, many=False, required=False,
error_messages={'does_not_exist': org_consts.DISTRICT_NOT_EXIST}
)
有关详细信息,请参阅here
答案 1 :(得分:0)
即使PrimaryKeyRelatedField
是Field
,但在使用required=False
进行初始化时,它的工作方式也不同。就像Remi写的那样,当前版本的DRF(3.5.X)支持读/写字段的唯一方法是allow_null
这些字段(除了使用一些奇怪的解决方法)。
API必须发送一个空字段,并且在对象表示即 Serializer.data
中,这些字段将具有None值。因为在我的情况下,我不能没有我修改Serialzier.to_representation
方法的值,如下所示:
def to_representation(self, instance):
"""Excludes fields with None value from representation
"""
ret = super().to_representation(instance)
return {field: value for (field, value) in ret.items()
if value is not None}