我有一个表示Status
的模型-并有一个来自Status
模型的Object
的外键。我希望能够创建新对象,但又不想允许创建更多Status
条目(有一组5个预定义的条目已迁移到数据库中)。我相信我已经找到了如何以仅重用现有Status
条目的方式构造序列化程序的方法,但是我不确定这是否是执行此类操作的最佳方法...
一些简化的代码:
class StatusSerializer(serializers.ModelSerializer):
class Meta:
model = Status
fields = ('name',)
def to_representation(self, obj):
return obj.name
def to_internal_value(self, data):
return {
'name': data
}
class ObjectSerializer(serializers.ModelSerializer):
status = StatusSerializer(read_only=True)
class Meta:
model = Object
fields = ('obj_name', 'status',)
def create(self, validated_data):
# We do not want to create new statuses - only use existing ones
status = Status.objects.get(name=self.initial_data['status'])
return Object.objects.create(status=status, **validated_data)
def update(self, instance, validated_data):
instance.obj_name = validated_data.get('obj_name', instance.obj_name)
# We do not want to create new statuses - only use existing ones
instance.status = Status.objects.get(name=self.initial_data['status']) if 'status' in self.initial_data else instance.status
return instance
如上所示,当显示Status
对象时,我也将其展平-例如我将以下内容
{
'obj_name': 'ObjectName',
'status': {
'name': 'StatusName'
}
}
进入
{
'obj_name': 'ObjectName',
'status': 'StatusName'
}
这似乎很好用-但是我不确定如何处理API用户给我一个无效的Status
名称的情况。现在,该API会冒泡从Status.DoesNotExist
个请求中提出一个Status.objects.get(...)
异常-我是否应该捕捉到该异常并重新引发序列化器/视图所期望的东西?
谢谢!
编辑:意识到我的问题并不十分清楚...
Status
对象的一种好方法-并强制所有创建的Object
将使用这些状态之一?Object
名称创建Status
的情况的最佳方法是什么?答案 0 :(得分:1)
您可以在validate
中使用ObjectSerializer
方法。
class ObjectSerializer(serializers.ModelSerializer):
status = StatusSerializer(read_only=True)
class Meta:
model = Object
fields = ('obj_name', 'status',)
def validate(self, attrs):
validated_data = super().validate(attrs)
status = self.initial_data.get('status')
# Here assuming that None is not the valid value for status
if status is not None:
status_obj = Status.objects.filter(name=status)
if not status_obj:
raise serializer.ValidationError('Invalid Status')
status_obj = status_obj[0]
validated_data['status'] = status_obj
return validated_data
# Nothing special to be done in create/update since we are sending data
# in validated_data which will directly sent to the instance.
# def create(self, validated_data):
# We do not want to create new statuses - only use existing ones
# status = Status.objects.get(name=self.initial_data['status'])
#return Object.objects.create(status=status, **validated_data)
#def update(self, instance, validated_data):
# instance.obj_name = validated_data.get('obj_name', instance.obj_name)
# We do not want to create new statuses - only use existing ones
# instance.status = Status.objects.get(name=self.initial_data['status']) if 'status' in self.initial_data else instance.status
# return instance
如果您可以使用不同的键来读写status
,则可以像这样修改ObjectSerializer
:
class ObjectSerializer(serializer.ModelSerializer):
status = serializer.SlugRelatedField(slug_field='name', queryset=Status.objects.all(), write_only=True)
status_data = StatusSerializer(read_only=True, source='status')
class Meta:
model = Object
fields = ('obj_name', 'status', 'status_data')
在这种情况下,如果您将{'obj_name': 'ObjectName', 'status': 'StatusName'}
数据传递给序列化程序,则序列化程序将首先检查所提供查询集的StatusName
字段中的name
值(在这种情况下,使用all
),如果无效则加注ValidationError
。如果有效,则将status
保存在实例的字段中。