Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Piston: How can I exclude nested fields from handler results? Is it even possible?

I am putting the finishing touches on an API I have written for a Django app utilizing django-piston. The API is able to search by request or IP address which are Request or IPAddress instances respectively. Each request can have 1 or more IPAddress associated with it.

So, for example I have an API call that will show all IPAddress objects matching an activity status of "active", "inactive", or "all" (for either). The Request to which each IPAddress instance is associated is available as IPAddress.request.

The problem I am having is that Request.inputter is a foreign key to the User instance of the person who provisioned the request. When my results are returned from the handler I have created for this API call, all fields from the User instance are displayed, including password.

This is bad; I do not want this.

So here is my handler:

class SearchByIPStatusHandler(BaseHandler):
    model = IPAddress
    allowed_methods = ('GET',)
    anonymous = AnonymousIPHandler

    def read(self, request, status):
        """
        Returns IP addresses based on activity status.  
        Status: 'active', 'inactive', 'all'

        """
        if status == 'all':
            return self.model.objects.all()
        else:
            active = True if (status=='active') else False
            return self.model.objects.filter(active=active)

And here is an example of the results from /api/show/all/:

<response>
  <resource>
    <updated>2010-02-05 17:08:53.651729</updated>
    <expires>2010-02-12 17:08:23</expires>
    <created>2010-02-05 17:08:53.625318</created>
    <nexthop>255.255.255.255</nexthop>
    <netmask>255.255.255.254</netmask>
    <address>2.4.6.80/31</address>
    <active>True</active>
    <id>4</id>
    <request>
      <updated>2010-02-05 17:08:53.382381</updated>
      <created>2010-02-05 17:08:53.382313</created>
      <expires>2010-02-12 17:08:23</expires>
      <incident>20100212-badthings-01</incident>
      <reason>bad things happened</reason>
      <inputter>
        <username>jathan</username>
        <first_name>Jathan</first_name>
        <last_name>McCollum</last_name>
        <is_active>True</is_active>
        <email>[email protected]</email>
        <is_superuser>True</is_superuser>
        <is_staff>True</is_staff>
        <last_login>2010-02-05 18:55:51.877746</last_login>
        <password>[ENCRYPTED STRING I REDACTED]</password>
        <id>1</id>
        <date_joined>2010-01-28 09:56:32</date_joined>
      </inputter>
      <requester>joeuser</requester>
      <active>True</active>
    </request>
  </resource>
</response>

All I really want in the results is the inputter.username, not all of the other stuff. I have tried various iterations of implementing an exclude attribute on the handler to no avail. If I just skip the entire request field, that works fine, like so:

In handler:

exclude = ('request', )

Which results in:

<response>
  <resource>
    <updated>2010-02-05 17:08:53.651729</updated>
    <expires>2010-02-12 17:08:23</expires>
    <created>2010-02-05 17:08:53.625318</created>
    <nexthop>255.255.255.255</nexthop>
    <netmask>255.255.255.254</netmask>
    <address>2.4.6.80/31</address>
    <active>True</active>
    <id>4</id>
  </resource>
</response>

But these results are also not what I want.

So, finally, my question:

How can I exclude nested fields from handler results? Is it even possible?

I have tried various iterations of the following, all of which either have no result, or unintended results:

# try to exclude request.inputter
exclude = ( ('request', ('inputter', ), ) )

# try to exclude request.inputter.password
exclude = ( ('request', ('inputter', ('password', ) ) ) ) 

I assume that I am misunderstanding or misusing the way field exclusions are done in this context, so any enlightenment on this topic is greatly appreciated.

like image 394
jathanism Avatar asked Feb 07 '10 00:02

jathanism


1 Answers

You can get the desired result by specifying the desired fields via the handler's fields = clause.

Model fields coming from foreign keys can be specified like this:

('foreign_model_field', ('nested_field1', 'nested_field2'))

In your case, the following should work (some of your fields left out for brevity):

fields = ('updated', 'expires', 'created', 
    ('request', ('incident', 'reason', ('inputter', ('username',)))))
like image 191
flanth Avatar answered Oct 05 '22 18:10

flanth