ndb 模型 - 检索有序的属性名称集 [英] ndb Model - retrieve ordered set of property names
问题描述
我经常被要求将存储在 NDB 模型中的数据导出到 csv.为此,我通常会写这样的模型:
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)
请注意,需要使用 fieldnames 方法来确定输出 csv 中字段的顺序.这种方法的问题在于,对于任何具有大量属性的模型,添加 fieldnames
方法都是丑陋的重复工作.理想情况下,我想在声明属性时简单地对它们进行排序,并按照 fieldnames
的相同顺序检索它们.有没有办法按顺序检索这些属性?Foo._properties
按字母顺序排列.
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.
推荐答案
据我所知,如果不亲自解析源代码,这是不可能的.幸运的是,有了 python 的包括电池"的心态,这并不太难.您可以使用 inspect
获取源代码,然后您可以使用 ast
来解析源代码和排序:
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
请注意,这里的方法几乎是通用的.我使用了 ndb.Model
s 具有 _properties
属性的知识,但该信息可能可以从 dir
或 inspect 中收集.getmembers
以便可以修改 order_properties
以使其完全正常工作.
Note that the approach here is almost general. I used the knowledge that ndb.Model
s 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.
这篇关于ndb 模型 - 检索有序的属性名称集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!