ndb模型-检索属性名称的有序集合 [英] ndb Model - retrieve ordered set of property names

查看:90
本文介绍了ndb模型-检索属性名称的有序集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经常有人问我将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']

在导出模块中,类似

# 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具有_properties属性的知识,但是可以从dirinspect.getmembers收集信息,因此可以修改order_properties使其完全正常工作.

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.

这篇关于ndb模型-检索属性名称的有序集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆