动态创建YAML/JSON模型

10 投票
1 回答
4501 浏览
提问于 2025-04-16 19:20

我正在尝试使用MongoEngine,这是一个用于Python的库,可以和MongoDB一起使用。我可以像网站上的这个例子一样定义一个模型:

class User(Document):
    email = StringField(required=True)
    first_name = StringField(max_length=50)
    last_name = StringField(max_length=50)

这个方法非常有效,MongoEngine真的很好用。不过,我想进一步探索一下,想知道是否可以在某个文件中用JSON或YAML等格式定义我的模型,然后再用它来创建模型。这样的话,JSON中的声明可能看起来像这样:

{
    "model":"User",
    "fields":{
        "email":{
            "type":"string",
            "required":"true"
        },
        "first_name":{
            "type":"string",
            "max_length":"50"
        },
        "last_name":{
            "type":"string",
            "max_length":"50"
        }
    }
}

接着,我会解析这个JSON并用它来创建模型。也许我每次修改模型定义时,只需要进行一次简单的导入操作,或者每次都解析整个JSON。这种做法怎么样?我只是想让使用这个应用的人能够定义自己的模型,而不需要深入代码。欢迎任何关于动态创建模型的想法。

1 个回答

4

如果你打算使用YAML格式的话,pyyaml这个库非常简单好用,它会自动把数据转成Python里内置的数据结构(或者你自己定义的更复杂的数据类型)。

不管你选择什么,我都强烈推荐Rx作为验证工具,这样你可以轻松检查加载的文件是否完整。*

至于如何用这个来创建一个模型,你可以使用内置的函数type(这里不是指type(object),而是type(name, bases, dict)),这个函数会“返回一个新的类型对象。这实际上是类声明的一种动态形式。”

所以,你可以这样调用:

def massage(fields_dict):
    #transform your file format into a valid set of fields, and return it

user_class = type(yaml_data['model'], Document, massage(yaml_data['fields']) )

*我在过去的八个小时里恰好同时使用了这两个工具,它们配合得非常好,比如:

import yaml
import Rx

data = yaml.load(open("foo.yaml")
rx = Rx.Factory({ "register_core_types": True })
schema = rx.make_schema(yaml.load(open("schema.yaml")))

if not schema.check(data):
    raise ValueError("data file contents are not in a valid format")

撰写回答