具有通用外键的 DRF 序列化程序 - 在保存之前检查给定的对象 ID 是否存在
DRF serializer with generic foreign key - check if given object ID exists before saving
我试图找到一种方法来检查 IntegerField
中的给定对象 ID 是否存在(用于序列化程序中的通用关系),就像 PrimaryKeyRelatedField
中的一样。
到目前为止,我采用了这种方法:
models.py:
class Comment(models.Model):
person = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
content_type = models.ForeignKey(ContentType, limit_choices_to={'pk__in': CONTENT_TYPES_PK})
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
serializers.py:
class CommentSerializer(serializers.ModelSerializer):
person = UserSerializer(read_only=True, default=serializers.CurrentUserDefault())
content_type = serializer.PrimaryKeyRelatedField(queryset=ContentType.objects.filter(pk__in=CONTENT_TYPES_PK), write_only=True)
object_id = IntegerField(write_only=True)
class Meta:
model = Comment
extra_kwargs = {'created': {'read_only': True}}
exclude = ('content_object',)
def create(self, validated_data):
obj = Comment(**validated_data)
if not obj.content_object:
raise serializers.ValidationError({'object_id': ['Invalid pk "'+str(obj.object_id)+'" - object does not exist.']})
obj.save()
return obj
但这不是一种可靠的方法,因为它实际上不会引发字段错误 - 它只是模仿它,因此在 API 浏览器中该字段不会突出显示。我想知道是否有更好的解决方案?提前致谢!
P.S。这是提交表单后的样子:
我以某种方式做到了 - 删除了子类 create
方法并添加了这个:
def validate(self, attrs):
try:
attrs['content_object'] = attrs['content_type'].model_class().objects.get(pk=attrs['object_id'])
except:
raise serializers.ValidationError({'object_id': ['Invalid pk "'+str(attrs['object_id'])+'" - object does not exist.']})
return attrs
It now highlights the field 但外观与 PrimaryKeyRelatedField
的不同。我认为有一些代码可以检查从哪里抛出异常,如果它来自那个字段,那么它会以不同的方式显示它,否则默认情况下。我想不出对这种行为的另一种解释,因为它引发了同样的 ValidationError
.
用户extra_kwargs简单易用我正在分享,请在序列化器字段后应用它。
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = testModel
fields = ('id','state','city','first_name',)
extra_kwargs = {
"state": {
'allow_null': False, 'required': True,
"error_messages" : {
"null" : "State is mandatory.",
"invalid": "State should be valid id",
"incorrect_type": "State should be valid id",
"does_not_exist": "State should be valid id",
"required":"State is mandatory.",
"blank":"State is mandatory."
}
},
}
我试图找到一种方法来检查 IntegerField
中的给定对象 ID 是否存在(用于序列化程序中的通用关系),就像 PrimaryKeyRelatedField
中的一样。
到目前为止,我采用了这种方法:
models.py:
class Comment(models.Model):
person = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
content_type = models.ForeignKey(ContentType, limit_choices_to={'pk__in': CONTENT_TYPES_PK})
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
serializers.py:
class CommentSerializer(serializers.ModelSerializer):
person = UserSerializer(read_only=True, default=serializers.CurrentUserDefault())
content_type = serializer.PrimaryKeyRelatedField(queryset=ContentType.objects.filter(pk__in=CONTENT_TYPES_PK), write_only=True)
object_id = IntegerField(write_only=True)
class Meta:
model = Comment
extra_kwargs = {'created': {'read_only': True}}
exclude = ('content_object',)
def create(self, validated_data):
obj = Comment(**validated_data)
if not obj.content_object:
raise serializers.ValidationError({'object_id': ['Invalid pk "'+str(obj.object_id)+'" - object does not exist.']})
obj.save()
return obj
但这不是一种可靠的方法,因为它实际上不会引发字段错误 - 它只是模仿它,因此在 API 浏览器中该字段不会突出显示。我想知道是否有更好的解决方案?提前致谢!
P.S。这是提交表单后的样子:
我以某种方式做到了 - 删除了子类 create
方法并添加了这个:
def validate(self, attrs):
try:
attrs['content_object'] = attrs['content_type'].model_class().objects.get(pk=attrs['object_id'])
except:
raise serializers.ValidationError({'object_id': ['Invalid pk "'+str(attrs['object_id'])+'" - object does not exist.']})
return attrs
It now highlights the field 但外观与 PrimaryKeyRelatedField
的不同。我认为有一些代码可以检查从哪里抛出异常,如果它来自那个字段,那么它会以不同的方式显示它,否则默认情况下。我想不出对这种行为的另一种解释,因为它引发了同样的 ValidationError
.
用户extra_kwargs简单易用我正在分享,请在序列化器字段后应用它。
class TestSerializer(serializers.ModelSerializer):
class Meta:
model = testModel
fields = ('id','state','city','first_name',)
extra_kwargs = {
"state": {
'allow_null': False, 'required': True,
"error_messages" : {
"null" : "State is mandatory.",
"invalid": "State should be valid id",
"incorrect_type": "State should be valid id",
"does_not_exist": "State should be valid id",
"required":"State is mandatory.",
"blank":"State is mandatory."
}
},
}