Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using related fields in serializers trigger SynchronousOnlyOperation #47

Open
G4DavidAlmeida opened this issue Sep 8, 2024 · 1 comment

Comments

@G4DavidAlmeida
Copy link

G4DavidAlmeida commented Sep 8, 2024

First, I would like to voluntter to contribute to the project, specific in this issue from start, but before that, lets talk about the issue itself

When we use related fields in serializers, a django.core.exceptions.SynchronousOnlyOperation is raised

that is my serializer who i will use as example (it's from my application)

class ApplyPermissionTokenSerializer(async_serializers.Serializer):
    permission = serializers.PrimaryKeyRelatedField(
        queryset=acc_models.PermissionToken.objects.all())

    def validate_permission(self, value: 'acc_models.PermissionToken'):
        if value.expire_in < timezone.now():
            raise serializers.ValidationError(
                _('O token de permissão expirou.'))
        return value

    def apply_permission(self):
        request = self.context.get('request')
        permission: acc_models.PermissionToken = self.validated_data['permission']
        permission.bussines.apply_permission(request.user)
        return permission

when i debug the PrimaryKeyRelatedField, the error is raised on return queryset.get(pk=data)

class PrimaryKeyRelatedField(RelatedField):
    default_error_messages = {
        'required': _('This field is required.'),
        'does_not_exist': _('Invalid pk "{pk_value}" - object does not exist.'),
        'incorrect_type': _('Incorrect type. Expected pk value, received {data_type}.'),
    }

    def __init__(self, **kwargs):
        self.pk_field = kwargs.pop('pk_field', None)
        super().__init__(**kwargs)

    def use_pk_only_optimization(self):
        return True

    def to_internal_value(self, data):
        if self.pk_field is not None:
            data = self.pk_field.to_internal_value(data)
        queryset = self.get_queryset()
        try:
            if isinstance(data, bool):
                raise TypeError
            return queryset.get(pk=data) # raise SynchronousOnlyOperation
        except ObjectDoesNotExist:
            self.fail('does_not_exist', pk_value=data)
        except (TypeError, ValueError):
            self.fail('incorrect_type', data_type=type(data).__name__)

    def to_representation(self, value):
        if self.pk_field is not None:
            return self.pk_field.to_representation(value.pk)
        return value.pk

Well, the problem is obvious, the rest_framework implementation do not use the async/await implementation and due to that, related fields not work

I think the best approach to resolve this issue is to create async fields like ADRF does with serializers

I apologize in advance for any inconsistencies or poor writing, English is not my native language and this is the first time I've tried to contribute to open source projects.

@Vonfry
Copy link

Vonfry commented Sep 14, 2024

Some related issue #46, #48

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants