Serializer with generic foreign key - check if given object ID exists before saving

1,417 views
Skip to first unread message

MikiSoft

unread,
Aug 28, 2016, 12:34:59 PM8/28/16
to Django REST framework

I'm trying to find a way of checking whether given object ID in IntegerField exists (which is used for generic relation in serializer), like there is for PrimaryKeyRelatedField.

So far, I came with this approach:
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}}

    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

But this isn't a robust way of doing such, because it actually doesn't raise a field error - it just imitates it and therefore in API Viewer the field isn't highlighted. I wonder if there's some better solution for this? Thanks in advance!


P.S. This is how it looks like after submitting the form (click on the image to enlarge):

MikiSoft

unread,
Aug 29, 2016, 8:17:59 AM8/29/16
to Django REST framework

I've made it somehow - removed subclassed create method and added this instead:


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

And is how it looks like:


As it can be seen, it now highlights the field but the appearance differs from the one for PrimaryKeyRelatedField. I think that there's some code which checks from where the exception is thrown, and if it's from that field then it shows it differently, else it goes by default. I couldn't think of another explanation for that behavior, because it raises the same ValidationError.

Reply all
Reply to author
Forward
0 new messages