python list mysteriously getting set to something within my django/piston handler

Posted by Anverc on Stack Overflow See other posts from Stack Overflow or by Anverc
Published on 2010-03-31T15:14:55Z Indexed on 2010/03/31 15:23 UTC
Read the original article Hit count: 373

Filed under:
|
|

To start, I'm very new to python, let alone Django and Piston.

Anyway, I've created a new BaseHandler class "class BaseApiHandler(BaseHandler)" so that I can extend some of the stff that BaseHandler does. This has been working fine until I added a new filter that could limit results to the first or last result. Now I can refresh the api page over and over and sometimes it will limit the result even if I don't include /limit/whatever in my URL... I've added some debug info into my return value to see what is happening, and that's when it gets more weird.

this return value will make more sense after you see the code, but here they are for reference:

When the results are correct:

"statusmsg": "2 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02',}", 

when the results are incorrect (once you read the code you'll notice two things wrong. First, it doesn't have 'limit':'None', secondly it shouldn't even get this far to begin with.

"statusmsg": "1 hours_detail found with query: {'empid':'22','datestamp':'2009-03-02',with limit[0,1](limit,None),}",

It may be important to note that I'm the only person with access to the server running this right now, so even if it was a cache issue, it doesn't make sense that I can just refresh and get different results by hitting F5 while viewing: http://localhost/api/hours_detail/datestamp/2009-03-02/empid/22

Here's the code broken into urls.py and handlers.py so that you can see what i'm doing:

URLS.PY

urlpatterns = patterns('',
    #hours_detail/id/{id}/empid/{empid}/projid/{projid}/datestamp/{datestamp}/daterange/{fromdate}to{todate}/limit/{first|last}/exact
    #empid is required
    # id, empid, projid, datestamp, daterange can be in any order
    url(r'^api/hours_detail/(?:' + \
        r'(?:[/]?id/(?P<id>\d+))?' + \
        r'(?:[/]?empid/(?P<empid>\d+))?' + \
        r'(?:[/]?projid/(?P<projid>\d+))?' + \
        r'(?:[/]?datestamp/(?P<datestamp>\d{4,}[-/\.]\d{2,}[-/\.]\d{2,}))?' + \
        r'(?:[/]?daterange/(?P<daterange>(?:\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})(?:to|/-)(?:\d{4,}[-/\.]\d{2,}[-/\.]\d{2,})))?' + \
        r')+' + \
        r'(?:/limit/(?P<limit>(?:first|last)))?' + \
        r'(?:/(?P<exact>exact))?$', hours_detail_resource),

HANDLERS.PY

# inherit from BaseHandler to add the extra functionality i need to process the possibly null URL params
class BaseApiHandler(BaseHandler):
    # keep track of the handler so the data is represented back to me correctly
    post_name = 'base'
    # THIS IS THE LIST IN QUESTION - SOMETIMES IT IS GETTING SET TO [0,1] MYSTERIOUSLY
    # this gets set to a list when the results are to be limited
    limit = None

    def has_limit(self):
        return (isinstance(self.limit, list) and len(self.limit) == 2)

    def process_kwarg_read(self, key, value, d_post, b_exact):
        """
        this should be overridden in the derived classes to process kwargs
        """
        pass

    # override 'read' so we can better handle our api's searching capabilities
    def read(self, request, *args, **kwargs):
        d_post = {'status':0,'statusmsg':'Nothing Happened'}
        try:
            # setup the named response object
            # select all employees then filter - querysets are lazy in django
            # the actual query is only done once data is needed, so this may
            # seem like some memory hog slow beast, but it's actually not.
            d_post[self.post_name] = self.queryset(request)

            # this is a string that holds debug information... it's the string I mentioned before pasting this code
            s_query = ''

            b_exact = False
            if 'exact' in kwargs and kwargs['exact'] <> None:
                b_exact = True
                s_query = '\'exact\':True,'

            for key,value in kwargs.iteritems():
                # the regex url possibilities will push None into the kwargs dictionary
                # if not specified, so just continue looping through if that's the case
                if value == None or key == 'exact':
                    continue

                # write to the s_query string so we have a nice error message
                s_query = '%s\'%s\':\'%s\',' % (s_query, key, value)

                # now process this key/value kwarg
                self.process_kwarg_read(key=key, value=value, d_post=d_post, b_exact=b_exact)

            # end of the kwargs for loop
            else:
                if self.has_limit():
                    # THIS SEEMS TO GET HIT SOMETIMES IF YOU CONSTANTLY REFRESH THE API PAGE, EVEN THOUGH 
                    # THE LINE IN THE FOR LOOP WHICH UPDATES s_query DOESN'T GET HIS AND THUS self.process_kwarg_read ALSO
                    # DOESN'T GET HIT SO NEITHER DOES limit = [0,1]
                    s_query = '%swith limit[%s,%s](limit,%s),' % (s_query, self.limit[0], self.limit[1], kwargs['limit'])
                    d_post[self.post_name] = d_post[self.post_name][self.limit[0]:self.limit[1]]
                if d_post[self.post_name].count() == 0:
                    d_post['status'] = 0
                    d_post['statusmsg'] = '%s not found with query: {%s}' % (self.post_name, s_query)
                else:
                    d_post['status'] = 1
                    d_post['statusmsg'] = '%s %s found with query: {%s}' % (d_post[self.post_name].count(), self.post_name, s_query)
        except:
            e = sys.exc_info()[1]
            d_post['status'] = 0
            d_post['statusmsg'] = 'error: %s' % e
            d_post[self.post_name] = []

        return d_post

class HoursDetailHandler(BaseApiHandler):
    #allowed_methods = ('GET',)
    model = HoursDetail
    exclude = ()
    post_name = 'hours_detail'

    def process_kwarg_read(self, key, value, d_post, b_exact):
        if ...
            # I have several if/elif statements here that check for other things... 
            # 'self.limit =' only shows up in the following elif:
        elif key == 'limit':
            order_by = 'clock_time'
            if value == 'last':
                order_by = '-clock_time'
            d_post[self.post_name] = d_post[self.post_name].order_by(order_by)
            # TO GET HERE, THE ONLY PLACE IN CODE WHERE self.limit IS SET, YOU MUST HAVE GONE THROUGH
            # THE value == None CHECK????
            self.limit = [0, 1]

        else:
            raise NameError

    def read(self, request, *args, **kwargs):
        # empid is required, so make sure it exists before running BaseApiHandler's read method
        if not('empid' in kwargs and kwargs['empid'] <> None and kwargs['empid'] >= 0):
            return {'status':0,'statusmsg':'empid cannot be empty'}
        else:
            return BaseApiHandler.read(self, request, *args, **kwargs)

Does anyone have a clue how else self.limit might be getting set to [0, 1] ? Am I misunderstanding kwargs or loops or anything in Python?

© Stack Overflow or respective owner

Related posts about python

Related posts about django