Создание модели из YAML / JSON «на лету»

#python #json #mongodb #model #yaml

#python #json #mongodb #Модель #yaml

Вопрос:

Я пробую MongoEngine, библиотеку DRM для 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:

Если вы собираетесь использовать YAML, pyyaml совершенно безболезнен и автоматически выводит структуру данных, используя встроенные типы python (или даже более сложные типы, которые вы определяете).

В любом случае, я бы также настоятельно рекомендовал Rx в качестве средства проверки, чтобы вы могли легко проверить целостность загруженных файлов.*

Что касается использования этого для создания модели, вы можете использовать встроенную функцию type (не type(object) , но type(name, bases, dict) ), которая… «[r] создайте объект нового типа. По сути, это динамическая форма инструкции класса.»

Итак, вы можете вызвать:

 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")