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

Use 'source' to determine which fields should be autogenerated #93

Open
Philipp-Userlike opened this issue Feb 9, 2024 · 2 comments
Open

Comments

@Philipp-Userlike
Copy link

Philipp-Userlike commented Feb 9, 2024

It would be nice if one could use 'source' to change the name of a field in serialized data:

class MyModel(models.Model):
    id = models.AutoField(primary_key=True)


@dataclass
class MyDataclass:
    model: MyModel


class MyDataclassSerializer(DataclassSerializer):
    model_id = PrimaryKeyRelatedField(queryset=MyModel.objects.all(), source="model")

    class Meta:
        dataclass = MyDataclass

Right now this autogenerates another related field with the name 'model' and expects both to be in the serializer input data.

MyDataclassSerializer(data={"model_id": 1}).is_valid(raise_exception=True)
# raises rest_framework.exceptions.ValidationError: {'model': [ErrorDetail(string='This field is required.', code='required')]}

As a workaround I have to exclude the original like this:

class MyDataclassSerializer(DataclassSerializer):
    model_id = PrimaryKeyRelatedField(queryset=MyModel.objects.all(), source="model")

    class Meta:
        dataclass = MyDataclass
        exclude = ["model"]

Our use case is that we have both references and subserialized objects in our API, and we use '_id' as a postfix to identify references.

@oxan
Copy link
Owner

oxan commented Feb 10, 2024

I'm not sure if suppressing the autogeneration of a field if another field uses it as source would be a sensible default. I can imagine usecases where source is used to add another representation, instead of replacing the default one all together, and it's also a breaking change. I'll have to check, but I also think that it'd be different behaviour from what DRF's built-in ModelSerializer does.

@Philipp-Userlike
Copy link
Author

DRF built-in serializers are a bit different since they allow partial models by default. But when I set __all__ as fields I indeed get the same behaviour.

from django.db import models
from rest_framework import serializers


class MyModel(models.Model):
    id = models.AutoField(primary_key=True)


class MyModel2(models.Model):
    id = models.AutoField(primary_key=True)
    model = models.ForeignKey(MyModel, on_delete=models.CASCADE)


class MyModelSerializer(serializers.ModelSerializer):
    model_id = serializers.PrimaryKeyRelatedField(
        queryset=MyModel.objects.all(), source="model"
    )

    class Meta:
        model = MyModel2
        fields = "__all__"


MyModel(id=1).save()
MyModelSerializer(data={"model_id": 1}).is_valid(raise_exception=True)
# raises rest_framework.exceptions.ValidationError: {'model': [ErrorDetail(string='This field is required.', code='required')]}

I think probably it is more common that you have one representation of a field by 'source' and don't want to autogenerate another one, but seems hard to change now.

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