【发布时间】:2018-06-24 07:43:15
【问题描述】:
在 DRF 中使用可写嵌套序列化程序时,存在验证最终唯一字段和阻止更新父序列化程序的已知问题。这个问题在以下问题中被问过很多次:
- Unique validation on nested serializer on Django Rest Framework
- Django rest framework not creating object with FK to a model with unique=True field
为简单起见,我们以第一个问题为例:
class GenreSerializer(serializers.ModelSerializer):
class Meta:
fields = ('name',) #This field is unique
model = Genre
extra_kwargs = {
'name': {'validators': []},
}
class BookSerializer(serializers.ModelSerializer):
genre = GenreSerializer()
class Meta:
model = Book
fields = ('name', 'genre')
def create(self, validated_data):
# implement creating
def update(self, instance, validated_data):
# implement updating
现在的问题是唯一性验证也被丢弃以进行创建。这可以在视图中被截取,例如:
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer = BookSerializer
def perform_create(self):
# implement logic and raise ValidationError
但这感觉不太对,因为我们正在验证Genre 在BookViewSet 中的唯一性。
另一种选择是在BookSerializer 的create() 方法中实现验证,如第二个问题中所述(参见上面的列表)。
我在这两种解决方案中真正想念的是验证错误未附加到模型Genre 的字段name 并且表单中的用户输入丢失。
我想要将Genre.name 的验证错误添加到现有的验证错误中,保留用户输入并且仅用于创建而不是更新。
我的想法是这样的:
class GenreSerializer(serializers.ModelSerializer):
# ...
def validate_name(self, value):
# is it possible to check here if it is create or update?
if create: # this is a placeholder for the logic
if self.Meta.model.objects.filter(name=value).exists():
raise ValidationError('A genre with this name already exists.')
return value
# or to override the __init__ method
def __init__(self, *args, **kwargs):
super(GenreSerializer, self).__init__(*args, **kwargs)
# check if create or update
if create:
self.fields['name'].validators.append('validation logic')
这是否可能或是否有任何其他方法可以实现上述目标 - 在创建新实例时保留用户输入并将附加到字段 name 的验证错误添加到现有验证错误列表中?
【问题讨论】:
-
“保持使用过的输入”是什么意思?
-
“保留用户输入”是指在验证后保留表单中的所有用户输入。
-
我不明白。嵌套表单不起作用。
-
@Linovia 我发布了自己的答案,保留了表单中的用户输入。
标签: python django django-rest-framework