Can django-tastypie display a different set of fields in the list and detail views of a single resource?
Asked Answered
T

4

11

I would like for a particular django-tastypie model resource to have only a subset of fields when listing objects, and all fields when showing a detail. Is this possible?

Turn answered 21/5, 2012 at 22:14 Comment(0)
J
14

You would have to specify all fields in the actual ModelResource then override the get_list method to filter out only the fields you want to show. See the internal implementation of get_list on Resource to see how to override it.

However, note this will only apply on GET requests, you should still be able to POST/PUT/PATCH on the resource with all fields if you authorization limits allow you to do so.

In a nut shell, you want to hot patch the internal field list before full_dehydrate is called on all ORM objects returned by obj_get_list.

Alternatively, you can let the full dehydrate mechanism take place and just at the end of it remove the fields you don't want to show if you don't care about squeezing out as much as speed as possible. Of course you would need to do this only if the URL is invoked as a consequence of get_list call. There is a convenience method for this alter_list_data_to_serialize(request, to_be_serialized).

Just do:

class SomeResource(Resource):
    class Meta(...):
         ...
         field_list_to_remove = [ 'field1', 'field2' ]
         ...

    def alter_list_data_to_serialize(request, to_be_serialized):
        for obj in to_be_serialized['objects']:
            for field_name in self._meta.field_list_to_remove:
                del obj.data[field_name]
        return to_be_serialized
Jack answered 22/5, 2012 at 12:57 Comment(3)
This is a good idea, and I appreciate your answer. I wonder, though, if there's a way to defer the fields from the original query to avoid sending some rather large fields over the wire.Turn
Then I would suggest you simply create 2 resources, one that shows all fields and another that only shows your subset on the same model. It is the simplest way without much overhead. If you insist on it being the same resource, you can follow my initial recommendation on overloading get_list to only include your subset of fields when fetching them from ORM and serializing them.Jack
There should be del obj.data[field_name].Apathetic
G
22

You can also now use the use_in attribute on a field to specify the relevant resource to show the field in. This can either be list or detail, or a callback.

Grosswardein answered 16/4, 2013 at 10:38 Comment(2)
That should be the main answer. Much more obvious and clear than overriding methods.Saddlecloth
This is one of those cases where you should be able to change the "Approved" answer for those of us coming later to the party.Flanker
J
14

You would have to specify all fields in the actual ModelResource then override the get_list method to filter out only the fields you want to show. See the internal implementation of get_list on Resource to see how to override it.

However, note this will only apply on GET requests, you should still be able to POST/PUT/PATCH on the resource with all fields if you authorization limits allow you to do so.

In a nut shell, you want to hot patch the internal field list before full_dehydrate is called on all ORM objects returned by obj_get_list.

Alternatively, you can let the full dehydrate mechanism take place and just at the end of it remove the fields you don't want to show if you don't care about squeezing out as much as speed as possible. Of course you would need to do this only if the URL is invoked as a consequence of get_list call. There is a convenience method for this alter_list_data_to_serialize(request, to_be_serialized).

Just do:

class SomeResource(Resource):
    class Meta(...):
         ...
         field_list_to_remove = [ 'field1', 'field2' ]
         ...

    def alter_list_data_to_serialize(request, to_be_serialized):
        for obj in to_be_serialized['objects']:
            for field_name in self._meta.field_list_to_remove:
                del obj.data[field_name]
        return to_be_serialized
Jack answered 22/5, 2012 at 12:57 Comment(3)
This is a good idea, and I appreciate your answer. I wonder, though, if there's a way to defer the fields from the original query to avoid sending some rather large fields over the wire.Turn
Then I would suggest you simply create 2 resources, one that shows all fields and another that only shows your subset on the same model. It is the simplest way without much overhead. If you insist on it being the same resource, you can follow my initial recommendation on overloading get_list to only include your subset of fields when fetching them from ORM and serializing them.Jack
There should be del obj.data[field_name].Apathetic
Z
0

There is an open issue for this on GitHub, with a number of workarounds suggested there.

Zandrazandt answered 29/1, 2013 at 4:0 Comment(0)
L
0

Can also use the dehydrate(self, bundle) method.

def dehydrate(self, bundle): del bundle.data['attr-to-del] return bundle

Lepidopteran answered 5/6, 2014 at 11:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.