0

I'm working on a Google App Engine project using Python and MySqlDB, and the App Engine requires me to return a Message object to the endpoint.
This is how the returning class looks:

class ReturningClass(messages.Message):
    """Return Column values stored here."""
    ID = messages.IntegerField(1)
    Locality_Name = messages.StringField(2)
    Pincode = messages.IntegerField(3)
    No_of_LL = messages.IntegerField(4)
    No_of_Hospitals = messages.IntegerField(5)
    No_of_Hotels = messages.IntegerField(6)

    And So on...

There's around 30 columns that I want to fetch dynamically.

This below is a Collection of the ReturningClass

class ReturningClassCollection(messages.Message):
    """Collection of ReturningClass objects."""
    items = messages.MessageField(ReturningClass, 1, repeated=True)

And this is the Main Class that actually does all the returning:

class MainClass(webapp2.RequestHandler):
    def get(self,Columns):
        if (os.getenv('SERVER_SOFTWARE') and
            os.getenv('SERVER_SOFTWARE').startswith('Google App Engine/')):
            db = MySQLdb.connect(unix_socket='/cloudsql/' + _INSTANCE_NAME, db='DatabaseName', user='root')
        else:
            db = MySQLdb.connect(host='127.0.0.1', port=3306, db='DatabaseName', user='root')
        cursor = db.cursor()

        ReturningArray=ReturningClassCollection()

        query="SELECT %s FROM DemoTable"%(Columns)
        cursor.execute(query)

        for result in cursor.fetchall():
            ReturningArray.items.append(ReturningClass(
            ID = result[0] ,
            Locality_Name = cgi.escape(result[1]),
            Pincode = result[2],
            No_of_LL= result[3],
            No_of_Hospitals = result[4] 
            ))
        cursor.close()
        db.close()
        return ReturningArray

This works if I give the select statement the 5 expected column values that are hard coded into the returning cursor.
Ex:

query="SELECT ID,Locality_Name,Pincode,No_of_LL,No_of_Hospitals,No_of_Hotels 
FROM DemoTable"

But if I do:

query="SELECT ID,Locality_Name  
FROM DemoTable"

I get a:

IndexError: tuple index out of range

How do I get the

for result in cursor.fetchall():
     ReturningArray.items.append(ReturningClass(
     ??
     ))

to return only the columns that are in the select statement?

BoreBoar
  • 2,619
  • 4
  • 24
  • 39

1 Answers1

3

Your question isn't very clear. Obviously you can't pass columns you haven't obtained from the database.

If you're actually asking how to dynamically pass whatever columns you select into the message class, you could use a dictionary cursor and pass that dict into the message instantiation:

from MySQL import cursors
...
cursor = db.cursor(cursors.DictCursor)
...
for result in cursor.fetchall():
    returning_obj = ReturningClass(**result)
    returning_array.append(returning_obj)
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Yes! That's what I meant! I AM asking about how to pass whatever columns are in the select query to the message class dynamically. I'm new to python and I didn't know how to frame the question properly. Sorry about that, but could you explain a little more about how I should go about the dictionary cursors? There are some columns that return Strings while mostly the others return Integers. And what I was doing right now was mapping variables inside the class to the columns exactly. How do I replace all this using a Dictionary? – BoreBoar Mar 16 '15 at 10:10
  • 1
    Well, that's what I show above - that's what the `(**result)` does. And it shouldn't make any difference whether they're strings or ints, as long as the column type in the db is the same as the field type in the message protobuff. – Daniel Roseman Mar 16 '15 at 10:18
  • Alright, I've hit a wall :S Could you please give another example of passing a dictionary to a class? Should I have a dictionary value in the constructor parameters for the Class? Right now I get a Type error attempting this: `returning_obj = ReturningClass(**result) TypeError: _MessageClass object argument after ** must be a mapping, not tuple` – BoreBoar Mar 16 '15 at 11:37
  • Could you suggest a good link to read about this? I still don't understand whats happened completely. And I couldn't find a lot of information for DictCursors on google. But thanks for solvin this though! :D – BoreBoar Mar 16 '15 at 11:59
  • I don't understand whats happening here: `returning_obj = ReturningClass(**result)`. Could you explain it a bit? :) – BoreBoar Mar 16 '15 at 12:06
  • 1
    Look up "dict unpacking". There are various SO questions and articles explaining it. – Daniel Roseman Mar 16 '15 at 13:39