我经常被要求将存储在NDB模型中的数据导出到csv。为此,我通常最终写出这样的模型:
from google.appengine.ext import ndb
class Foo(ndb.Model):
monty = ndb.StringProperty()
python = ndb.StringProperty()
@property
@classmethod
def fieldnames(cls):
return ['monty', 'python']
并在导出模块中的内容
# 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
按字母顺序排列。
答案 0 :(得分:4)
据我所知,如果不自己解析源代码,这是不可能的。幸运的是,有了python的“电池包含”心态,这并不难。您可以使用inspect
获取源代码,然后您可以使用ast
来解析源代码并订购内容:
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
具有_properties
属性的知识,但该信息可能来自dir
或inspect.getmembers
,因此可以修改order_properties
以便它完全有效。
答案 1 :(得分:0)
我只是在做这件事,它可能充满了错误,但希望它能让你走上正确的道路:
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()
答案 2 :(得分:0)
google.appengine.ext.db
: db.Property
实例具有一个名为creation_counter
的属性,该属性在每次创建新实例时都会增加。因此,要获取按声明顺序排序的属性列表,可以执行以下操作:
sorted(Foo.properties().items(), key=lambda np: np[1].creation_counter)
(其中Foo
是db.Model
的实例)
google.appengine.ext.ndb
:相同,除了ndb.Property
属性称为_creation_counter
,因此等效代码为:
sorted(Foo._properties.items(), key=lambda np: np[1]._creation_counter)
(其中Foo
是ndb.Model
的实例)