我有一个 API 端点(在这个简化的示例中)创建一个“Stuff”对象,它具有仅根据其他字段之一的值才需要的字段。
作为一个粗略的示例,以下请求是有效的:
{
"type": "A"
"name": "Steve"
"Afield1": "hello"
"Afield2": "goodbye"
}
和
{
"type": "B"
"name": "Paul"
}
以下则不是,因为当
Afield1
= A时,
Afield2
和
type
应该是必填字段
{
"type": "A"
"name": "Steve"
}
它应该返回此错误:
{
"Afield1": [
"This field is required."
]
"Afield2": [
"This field is required."
]
}
这是 Django Rest Framework 中缺少字段的标准错误。具体来说,错误字典是在
to_internal_values()
文件中的 serializer.py
中构建的。
但是,序列化程序必须将这些字段定义为
required=False
,因为为了使类型“B”请求有效,类型“A”的字段必须是可选的。
因此,序列化器看起来像这样:
class StuffSerializer(serializers.ModelSerializer):
Afield1 = serializers.CharField(required=False)
Afield2 = serializers.CharField(required=False)
我正在寻找一种在发出请求后有条件地将 required 更改为 True 的方法。我尝试从序列化器访问 Field 上的
required
属性,但它似乎对实际 Field 对象没有生效。
class StuffSerializer():
def create(self, validated_stuff_data) -> Stuff:
for field in ["Afield1","Afield2"]:
if field not in validated_stuff_data:
# This gets the Field object for the missing field,
# and sets it to be required. This does NOT work
# because the change is not reflected on the field
# that gets validated after this loop
missing_field = self.get_fields()[field]
missing_field.required = True
# This calls validation for serializer
self.is_valid(raise_exception=True)
再次强调,我不想提出自己的自定义验证错误,而是想利用 DRF 中现有的验证逻辑。
可以使用序列化器中的 validate 方法来完成。
from rest_framework import serializers
class StuffSerializer(serializers.ModelSerializer):
Afield1 = serializers.CharField(required=False)
Afield2 = serializers.CharField(required=False)
def validate(self, attrs: dict) -> dict:
type = attrs.get("type", None)
field_1 = attrs.get("field_1", None)
field_2 = attrs.get("field_2", None)
# your condition
if type == "A":
if field_1 is None and field_2 is None:
raise serializers.ValidationError("Both `field_1` and `field_2` are required")
return attrs
如果
validate
方法引发错误,错误将采用以下格式
{
"non_field_errors": [
"Both `field_1` and `field_2` are required"
]
}