ndb Model - retrieve ordered set of property names

I'm often asked to export data stored in NDB models to csv. For that purpose, I usually ended up writing a model like this:

from google.appengine.ext import ndb class Foo(ndb.Model): monty = ndb.StringProperty() python = ndb.StringProperty() @property @classmethod def fieldnames(cls): return ['monty', 'python']

and in the export module something along the lines of

# pseudocode ... query = Foo.gql('where monty = :1', 'bunny') data = [littlefoo._to_dict() for littlefoo in query] fieldnames = Foo.fieldnames with open('outfile.csv', 'w') as f: writer = csv.DictWriter(f, fieldnames, dialect=dialect) writer.writerows(data)

Note that the fieldnames method is needed for determining the order of the fields in the output csv. The problem with this approach is that for any model with a significant number of attributes, adding the fieldnames method is ugly duplicate work. Ideally, I'd like to simply order the properties as I declare them, and retrieve them in the same order for fieldnames. Is there a way to retrieve these properties in order? Foo._properties is ordered alphabetically.


To my knowledge, this isn't possible without parsing the source for yourself. Luckily, with python's "batteries included" mentality, this isn't too hard. You can use inspect to get the source code and then you can use ast to parse the source and order things:

import ast import inspect class NodeTagger(ast.NodeVisitor): def __init__(self): self.class_attribute_names = {} def visit_Assign(self, node): for target in node.targets: self.class_attribute_names[target.id] = target.lineno # Don't visit Assign nodes inside Function Definitions. def visit_FunctionDef(self, unused_node): return None def order_properties(model): properties = model._properties source = inspect.getsource(model) tree = ast.parse(source) visitor = NodeTagger() visitor.visit(tree) attributes = visitor.class_attribute_names model._ordered_property_list = sorted(properties, key=lambda x:attributes[x]) return model @order_properties class Foo(object): c = 1 b = 2 a = 3 # Add a _properties member to simulate an `ndb.Model`. _properties = {'a': object, 'b': object, 'c': object} print Foo._ordered_property_list

Note that the approach here is almost general. I used the knowledge that ndb.Models have a _properties attribute, but that information could probably be gleaned from dir or inspect.getmembers so order_properties could be modified so that it works completely generally.


I'm just making this up, it's probably full of errors, but hopefully it starts you down the right path:

from google.appengine.ext.ndb import Property def get_field_names(ndbmodel): result = [] all_fields = dir(ndbmodel) for field in all_fields: if isinstance(getattr(ndbmodel, field), Property): result.append(field) return result.sort()


  • switch statement: “a constant value is expected”
  • Word Base/Stem Dictionary
  • iOS check if torch is on
  • Reading a file into a multidimensional array
  • Object and struct member access and address offset calculation
  • Create DicomImage from scratch using Dcmtk
  • Hardware Accelerated Image Scaling in windows using C++
  • Magento Fatal error: Maximum execution error solution, on WAMP
  • Breeze - Deleted Items nav properties bug
  • How to do unit test for HttpContext.Current.Server.MapPath
  • How can I send an e-mail from a vbs script
  • Sails.js/waterline: Executing waterline queries in toJSON function of a model?
  • javaw.exe and eclipse startup problems
  • Can Jackson SerializationFeature be overridden per field or class?
  • How to redirect a user to a different server and include HTTP basic authentication credentials?
  • Window Size for Mac application
  • Validaiting emails with Net.Mail MailAddress
  • Join two tables and save into third-sql
  • Deserializing XML into class C#
  • Can I make an Android app that runs a web view in Chrome 39?
  • Trying to switch camera back to front but getting exception
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • How to model a transition system with SPIN
  • Javascript + PHP Encryption with pidCrypt
  • Timeout for blocking function call, i.e., how to stop waiting for user input after X seconds?
  • ORA-29908: missing primary invocation for ancillary operator
  • Function pointer “assignment from incompatible pointer type” only when using vararg ellipsis
  • Rails 2: use form_for to build a form covering multiple objects of the same class
  • Free memory of cv::Mat loaded using FileStorage API
  • Angular 2 constructor injection vs direct access
  • how does django model after text[] in postgresql [duplicate]
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • need help with bizarre java.net.HttpURLConnection behavior
  • How does Linux kernel interrupt the application?
  • LevelDB C iterator
  • Linking SubReports Without LinkChild/LinkMaster
  • python draw pie shapes with colour filled
  • Programmatically clearing map cache
  • How to Embed XSL into XML
  • Converting MP3 duration time