我有以下内容:
class ClientSubscription(models.Model):
activity = models.ForeignKey(Activity)
client = models.ForeignKey(Client)
subscription_date_start = models.DateField(blank = True, null = True)
subscription_date_end = models.DateField(blank = True, null = True)
class Meta:
unique_together = ('activity', 'client')
以及以下序列化程序:
class ActivitySerializer(serializers.ModelSerializer):
activity_slug = serializers.CharField(read_only = True, required=False)
activity_type = serializers.PrimaryKeyRelatedField(read_only = True)
activity_name = serializers.CharField(read_only = True, source = 'activity_type', required=False)\
is_active = serializers.BooleanField(required=False)
class Meta:
model = Activity
fields = ('id', 'activity_type', 'is_active', 'activity_name', 'activity_slug')
class ClientSubscriptionSerializer(serializers.ModelSerializer):
activity = ActivitySerializer(read_only=False)
client = serializers.PrimaryKeyRelatedField(queryset=Client.objects.all())
subscription_date_start = serializers.DateField(format="%Y-%m-%d")
subscription_date_end = serializers.DateField(format="%Y-%m-%d")
class Meta:
model = ClientConcernedSubscriptions
fields = ('id', 'activity', 'client', 'subscription_date_start', 'subscription_date_end')
序列化方面的一切都很好 - 但我无法验证或保存反序列化的数据,并收到以下错误:
TypeError: int() argument must be a string or a number, not 'OrderedDict'
我查看了this,但我似乎无法使用此解决方案。
这是收到的数据:
{u'subscription_date_end': u'2015-10-01',
'client': 8,
u'subscription_date_start': u'2014-10-01',
u'activity': {u'activity_name': u'Name', u'is_active': True, u'id': 14597, u'activity_slug': u'slug', u'activity_type': u'9'},
u'id': 58782}
我确信这是必须相当普遍的事情,而且我做的事情很愚蠢。我希望能够保存我的对象,以及能够改变相关领域的字段。
答案 0 :(得分:4)
这是因为rest_framework中的唯一验证器需要嵌套关系的整数值,如果为相关字段创建自定义序列化程序,则反序列化会提供dict而不是主键值。
所以我做了这个解决方案,希望对你也有所帮助。
像这样创建一个Custom Validator:
class UniqueTogetherNestedValidator(object):
def __init__(
self, queryset=None, simple_fields=None, dict_fields=None,
message='Not unique together value'):
if queryset is None or simple_fields is None or dict_fields is None:
raise TypeError(
'__init__() missing 3 required positional arguments: \
\'queryset\', \'simple_fields\' and \'dict_fields\''
)
else:
self.queryset = queryset
self.simple_fields = simple_fields
self.dict_fields = dict_fields
self.message = message
def __call__(self, value):
unique = {}
for f in self.simple_fields:
unique[f] = value[f]
for f in self.dict_fields:
unique['{}__id'.format(f)] = value[f]['id']
print(unique)
if self.queryset.filter(**unique).exists():
raise serializers.ValidationError(self.message)
然后从序列化程序中的Meta调用它,至少提供queryset,simple_fields(来自de model的字段)和dict_fields(嵌套字段)。