rsinger86 / drf-flex-fields

Dynamically set fields and expand nested resources in Django REST Framework serializers.
MIT License
740 stars 61 forks source link

Can't rename expanded field (because "source" keyword is excluded) #72

Closed daviddjia closed 3 years ago

daviddjia commented 3 years ago

I'm trying to rename a field that is also a nested serializer. Normally, I'd use the source kwarg during serializer instantiation for this, but if I define the serializer in expandable_fields, it doesn't work. In the code below, if I set the field name (in the FooBarSerializer) to foo_bar_details, everything works. But if I set it to details and then include the source field, I get this error (this approach works fine if I instantiate the serializer normally, outside of expandable_fields):

  File "/Users/david/src/proj/venv/lib/python3.7/site-packages/rest_framework/serializers.py", line 1325, in build_unknown_field
    (field_name, model_class.__name__)
django.core.exceptions.ImproperlyConfigured: Field name `details` is not valid for model `FooBar`.
class FooBarDetails(django.db.models.Model):
    id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)
    properties = models.CharField(max_length=256, null=True, blank=True)  
    class Meta:
        db_table = 'foo_bar_details'

class FooBar(django.db.models.Model):
    id = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True)
    name = models.CharField(max_length=256, null=True, blank=True)  
    foo_bar_details = models.ForeignKey(FooBarDetails, on_delete=models.SET_NULL, null=True)
    class Meta:
        db_table = 'foo_bar'

class FooBarDetailsSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = FooBarDetails
        fields = ('properties')

class FooBarSerializer(FlexFieldsModelSerializer):
    expandable_fields = {
        'details': (
            FooBarDetailsSerializer,
            {'required': False, 'many': False, 'read_only': True, 'source': 'foo_bar_details'},
        ),
    }
    class Meta:
        model = FooBar
        fields = (
            'id',
            'name',
            'details',
        )

I think I've traced this issue to here: https://github.com/rsinger86/drf-flex-fields/blob/master/rest_flex_fields/serializers.py#L102 Is there a reason that the source keyword is purposefully being excluded from the serializer instantiation?

rsinger86 commented 3 years ago

DRF errors out if the source argument is the same value as the field. I think that's why I did this. But I can see it having unintended side effects so I'll remove.