将字符串转换为NDB属性的正确类型的正确方法?

时间:2015-03-04 17:24:51

标签: python google-app-engine

如果我有来自GET或POST请求的一些(字符串)值与关联的Property个实例,一个IntegerProperty和一个TextProperty,比方说,有没有办法转换值为正确(用户)类型而没有冗长乏味的isinstance调用链?

我希望重现这种功能(为清晰起见,省略了所有输入验证):

for key, value in self.request.POST.iteritems():
    prop = MyModel._properties[key]

    if isinstance(prop, ndb.IntegerProperty):
        value = int(value)
    elif isinstance(prop, (ndb.TextProperty, ndb.StringProperty)):
        pass # it's already the right type
    elif ...
    else
        raise RuntimeError("I don't know how to deal with this property: {}"
                           .format(prop))

    setattr(mymodelinstance, key, value)

例如,如果有办法从int获取IntegerProperty类,从bool等获得BooleanProperty类,则可以完成工作

就我所见,ndb元数据API并没有真正解决这个问题;但get_representations_of_kind我可以减少案件数量。

2 个答案:

答案 0 :(得分:2)

您可以使用dict在用户定义的类型与内置类型之间进行映射,方法是使用对象的type作为键,将内置类型作为值。

F.e。

class IntegerProperty(int):
    pass

class StringProperty(str):
    pass

a, b  = IntegerProperty('1'), StringProperty('string')

def to_primitive(obj):
    switch = {IntegerProperty: int, StringProperty: str}
    return switch[type(obj)](obj)

for x in (a, b):
        print(to_primitive(x))

因为此处键是对象的类型而不是isinstance检查,如果类型不在,则会出现多个用户定义类型映射到单个内置类型KeyError dict。因此,您必须将每个用户定义的类型显式添加到交换机dict

F.e。

class TextProperty(StringProperty):
    pass
switch = {IntegerProperty: int, StringProperty: str, TextProperty: str}

上面我们已将新TextProperty添加到switch,即使TextPropertyStringProperty的子类。如果您不想这样做,我们必须从isinstance检查来获取密钥 这是怎么做的;

class IntegerProperty(int):
    pass

class StringProperty(str):
    pass

class TextProperty(StringProperty):
    pass

a, b, c = IntegerProperty('1'), StringProperty('string'), TextProperty('text')

def to_primitive(obj):
    switch = {IntegerProperty: int, StringProperty: str}
    key = filter(lambda cls: isinstance(obj, cls), switch.keys())
    if not key:
        raise TypeError('Unknown type: {}'.format(repr(obj)))
    key = key[0]

    return switch[key](obj)

for x in (a, b, c):
        print(to_primitive(x))

答案 1 :(得分:1)

有一个名为WTForms的Python软件包对此非常有用,并且通常使表单处理成为一种更愉快的体验。

这是一个非常简单的例子:

class MyForm(wt.Form):
    text = MyTextAreaField("Enter text")
    n = wt.IntegerField("A number")

f = MyForm(self.request.POST)
f.validate()
print f.text.data
print f.n.data

调用f.validate()会自动将POST数据转换为表单指定的数据类型。因此f.text.data将是一个字符串,而f.n.data将是一个整数。

它还可以优雅地处理无效数据。如果用户输入整数字段的字母,则f.n.data将为None。您还可以指定容易合并到网页中的错误消息。

WTForms从表单处理中获取了大量的苦差事!