Question

I'm a little confused about the difference between Resource and ModelResource in django tastypie.

I have a Resource

class ReportResource(ModelResource):
  class Meta:
     queryset = Report.objects.filter(deleted__isnull=True)
     resource_name = 'report'
     object_class = Report

When retrieving a list the field report_data should not be fetched ....

Is it possible to use the use_in option in a ModelResource ?

One alternative is using the full_dehydrate :

def full_dehydrate(self, bundle, for_list=False):   

    if for_list:
        # List view
        # Remove unnecessary fields from the bundle 

    # Detail view
    return super(ReportResource,self).full_dehydrate(bundle,for_list)

But removing the fields in dehydrate might cause poor performance since all the fields has already been fetched from the db.

EDIT

I'll explain further what i'm trying to achieve

When retrieving a list of reports using api/report/ I want to get a json array containing only the name and description of the report object.

When retrieving a single report using api/report/88387 I want to get a json containing all the fields in the model.

This is possible in the full_dehydrate function as explained above but in my opinion there must a built in solution. The use_in attribute of Resource Field seems like a good solution but i'm not sure how i can use it with a ModelResource.

There is an old issue on github about this and i was wondering if there is a solution.

Was it helpful?

Solution

Subclass the __init__ function in your ReportResource and set the use_in flag there, now that your fields have been populated:

def __init__(self, *args, **kwargs):
    # Call the object's parent, which will set up and populate
    # the Resource fields from the queryset provided
    super(ReportResource, self).__init__(*args, **kwargs)
    # Now loop through the fields of the resource, and when we
    # find the one we only want to be shown in the detail view,
    # set its use_in attr appropriately
    for field_name, field_object in self.fields.items():
        if field_name == 'report_data':
            field_object.use_in = 'detail'

(Generically, you could have this in a separate class that you mix in, and perhaps it could read the list of what you want from a variable in Meta, but this should do what you ask.)

The same sort of loop through self.fields.items() is used for the use_in check in Resource's full_dehydrate method, as you can see from the source code of resources.py.

OTHER TIPS

From my understanding, you can use use_in in the ModelResource.

ModelResource is Tastypie's "contrib" resource.

The ModelResource calls Resource's full_dehydrate method in the following methods:

[get_list, get_detail, post_list, put_list, put_detail, patch_list, patch_detail and get_multiple]

In each _list method the full_dehydrate method is called with the for_list=True and in each _detail method the full_dehydrate method is not called with the for_list (for_list=False is default)

When defining fields in your resource just add the use_in attribute ("all", "detail", "list") for each field that needs special attention, default is "all".

The usage of this attribute is in the full_dehydrate method. It skips dehydration for fields not matching the use_in attribute along side the for_list param.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top