creating mongoengine class dynamicly from json schema

|▌冷眼眸甩不掉的悲伤 提交于 2020-08-02 06:53:37

问题


i'm looking for a way to take my json schema and dynamically create a mongoengine class at runtime.

for example: the mongoengine class written below

class user(Document):
     _id  = StringField(required=False) # mongodb id
     name = StringField(required=True)  # user name
     email= StringField(required=False,regex="^[a-zA-Z0-9]*@mydomain.com$")  # user email

will be the same as the dynamically generated at runtime class generated from this schema

{
"type":"object",
"properties":{
    "_id"      : {"type":"string"},
    "name"     : {"type":"string"},
    "email"    : {"pattern":"^[a-zA-Z0-9]*@mydomain.com$"}
    }
}

any suggestions?


回答1:


You can create python classes dynamically, like below:

user_properties = { 
   '_id': StringField(required=False), # mongodb id
   'name': StringField(required=True), # user name
   'email': StringField(required=False,regex="^[a-zA-Z0-9]*@mydomain.com$"),  # user email
}
User = type("User", (Document, ), user_properties)

The remaining is only convertor from dict with "your schema" provided on input, that will be converted to dict user_properties .

Also, here is my answer to similar question "How to generate a model for a mongoengine Document from an already existing collection" which can also help.




回答2:


The jinja template engine has features that can be utilized to create a mongo class template that populates the property schemas in the class definition based on the type of each property. Then, we generate the desired Python class dynamically using a simple intermediate script that renders this template. The following is an example illustrating this concept. We start with the following project structure, which has a sample parent folder called Templates and three files:

Templates\
    - mongo_sample.schema.json
    - mongoclass_template.jinja
    - auto_mongo_class.py

Let's explore these files:

1. mongo_sample.schema.json:

This is the MongoDB schema document. A consistent schema helps create a standard Jinja template later:

{
  "type":"object",
  "required": ["name"],
  "properties":{
      "_id"      : {"type":"string"},
      "name"     : {"type":"string"},
      "email"    : {"pattern":"^[a-zA-Z0-9]*@mydomain.com$"}
    }
}

2. mongoclass_template.jinja:

This is the Jinja template for a Mongo class which will be used to render the desired Python Mongo class in the end. It makes use of the Jinja template language. Here's the reference for the Template Designer Documentation. Here, all we are doing is creating a template that covers all "type" cases and also parameters like "required" and "regex". Notice that a consistent schema is important:

from mongoengine import DynamicDocument, StringField, IntField

class Student(DynamicDocument):       
    {%- for prop, val in properties.items() %} 
    {%- if prop in required -%}
    {% set req = True %}
    {% else %}    
    {% set req = False %}
    {%- endif -%}
    {%- if val.pattern is defined -%}
    {% set patt = val.pattern %}    
    {% else %}
    {% set patt = None %} 
    {%- endif -%}  
    {%- if val.type == "string" -%}
    {{prop}} = StringField(required={{req}}, regex={{patt}})
    {%- elif val.type == "int" -%}
    {{prop}} = IntField(required={{req}})        
    {%- else -%} 
    {{prop}} = StringField(required={{req}}, regex="{{patt}}")       
    {%- endif -%}
    {%- endfor %}
    

3. auto_mongo_class.py:

This Python script parses through the JSON schema above to get the properties object, passes the necessary variables to the template render() method which will be used while rendering the template and finally writes to a Python file called models.py which is the final Mongo class:

import json
from jinja2 import Template

with open(r"mongo_sample.schema.json", "r") as schema_json:
    schema_tree = json.load(schema_json)
properties = schema_tree["properties"]
required = schema_tree["required"]
template = Template(open(r"mongoclass_template.jinja").read()).render(properties=properties, \
    required=required)

with open("models.py", 'w') as file_:
    file_.write(template)

Now, let's run this script:

python auto_mongo_class.py

A new Python script called models.py will appear in the project folder with the following contents:

from mongoengine import DynamicDocument, StringField, IntField

class Student(DynamicDocument):    
    
    _id = StringField(required=False, regex=None)
    
    name = StringField(required=True, regex=None)    
        
    email = StringField(required=False, regex="^[a-zA-Z0-9]*@mydomain.com$")


来源:https://stackoverflow.com/questions/33920062/creating-mongoengine-class-dynamicly-from-json-schema

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!