Search code examples
djangotastypie

Exclude a field from tastypie api


I need to exclude a field on the basis of the value of some other field. The relationship between them is as follows.

class Moo: 
   ...

class Too:
        moo = models.ForeignKey(Moo, related_name='moo_too')

        ...

class PooToo:
       moo = models.ForeignKey(Moo) 
       stature = models.PositiveSmallIntegerField(..)
       ...

class PooMooResource(ModelResource):

    moo = ToOneField(StandAloneMooResource, 'moo', full=True)
    class Meta:
        list_allowed_methods = ['get']
        queryset = PooMoo.objects.select_related('moo').all()

class StandAloneMooResource(ModelResource):

    too = ToManyField(TooResource,...)
    class Meta:
            queryset = Moo.objects.all()

Now I want to expose the too field in the API only when stature==0, otherwise not. I can use use_in for this, but the problem is I do not have the value of stature in StandAloneMooResource


Solution

  • Try something like this:

    class StandAloneMooResource(ModelResource):
    
        too = ToManyField(TooResource,...)
        class Meta:
            queryset = Moo.objects.all()
    
        def dehydrate_too(self, bundle):
            # if this method is run while dehdyrating PooMooResource.moo,
            # related_obj should be the related PooMoo
            if bundle.related_obj and bundle.related_obj.stature != 0:
                return None
            return bundle.data['too']
    

    Unfortunately the 'too' key will still be there, and tastypie will still go through the effort of retrieving the tutorials from the DB.

    This might be better:

    def foo(bundle):
        if bundle.related_obj and bundle.related_obj.stature != 0:
            return None
        return bundle.obj.tutorials.all()
    
    class StandAloneMooResource(ModelResource):
    
        too = ToManyField(TooResource, attribute=foo)
        class Meta:
            queryset = Moo.objects.all()
    
        def dehydrate(self, bundle):
            # to remove the 'tutorials' key
            if 'too' in bundle.data and not bundle.data['too']:
                del bundle.data['too']
            return bundle
    

    If bundle.related_obj isn't working:

    def foo(bundle):
        poomoo = None
        try:
            # assumes PooMoo.user a relation to User
            poomoo = PooMoo.objects.filter(moo=bundle.obj, user=bundle.request.user)[0]
        except IndexError:
            pass
        if poomoo and poomoo.stature != 0:
            return None
        return bundle.obj.too.all()