rsinger86 / drf-flex-fields

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

Expand not working as expected #29

Open keithjeb opened 5 years ago

keithjeb commented 5 years ago

I have the following models:

class UploadTemplate(models.Model):
    book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True)
    coupon_type = models.CharField(max_length=100)
class Book(models.Model):
    book_name = models.CharField(max_length=30)
    #....random other fields

and serializers as follows:

class TemplateSerializer(FlexFieldsModelSerializer):
    book = serializers.PrimaryKeyRelatedField(read_only=True)
    class Meta:
        model = UploadTemplate
        fields = ["coupon_type", "id", "book"]
        expandable_fields = {
            'book': ('BookSerializer', {
                'source': 'book'
            })
        }
class BookSerializer(FlexFieldsModelSerializer):
    class Meta:
        model = Book
        fields = "__all__"

If i make a call to http://localhost:8000/v1/coupons/templates/6/?expand=book I'd expect book to expand to the nested serializer. Unfortunately it doesn't and I've drawn a blank debugging.

My viewset:

from rest_flex_fields.views import FlexFieldsMixin

class UploadTemplateViewset(viewsets.ModelViewSet, FlexFieldsMixin):
    queryset = models.UploadTemplate.objects.all()
    serializer_class = serializers.UploadTemplateSerializer
    filterset_fields = ('book', )
    permit_list_expands = ['book']

    def get_queryset(self):
        print(is_expanded(self.request, 'book'))
        return models.UploadTemplate.objects.all()

confirms that book is expanded. (i,e, it prints True in the console).

Am I doing something obviously dumb, and if not, where should I start with debugging the issue? I'm on django 2, python 3.6

rsinger86 commented 5 years ago

As you're referencing the BookSerializer by string, try including the app name before it like this:

        expandable_fields = {
            'book': ('<app>.BookSerializer', {
                'source': 'book'
            })
        }
dmugtasimov commented 5 years ago

Same issue. I am referencing serializers by class:

    expandable_fields = {
        'company': (CompanyBasicSerializer, {}),
        'location': (LocationBasicSerializer, {}),
        'job_type': (JobTypeBasicSerializer, {}),
    }
dmugtasimov commented 5 years ago

Rolling back to version 0.3.5 fixes the issue.

yezyilomo commented 5 years ago

I was making something like this but for GET method only, I think I've managed to make it more advanced and flexible, for those who want to check it out it's django-restql. Feedback will be appreciated.

SamMorrowDrums commented 4 years ago

@rsinger86 I'd add to this, that it can be confusing because of the implementation of _should_field_exist means that if you use both fields, and expand, you need to explicitly add all items you want to expand to fields as well, otherwise they won't be returned.

In a way I feel like expand fields should be included in fields automatically rather than have to specify them twice, but in a sense I get how it is with the expected use case of fields=object returning object.id and requests with fields=object&expand=object returning the full Object serialized. I guess what I suggest has negative quirks such as expand=object with no fields specified would then return everything, plus an expanded object. Anyway, just mentioning the confusion, because it did get me for a while.

I had been using the expands to hide certain function fields that are database intensive (or that call external APIs, like auth token Amazon S3 file urls).

expandable_fields = {
            'company_logo': (serializers.CharField, {'source': 'company_logo'}),
            'link': (serializers.CharField, {'source': 'public_relative_url'}),
}

And it surprised me at first that I had to include them in the fields, as they are already in the expand list.

Maybe we could add to the docs, that when wanting expands while using the "fields" query you must specify both the "expand" and "fields" entry for example: fields=object&expand=object

Anyway, maybe it's obvious to others, but I did lose some time over it.