prawn-cake/simple-models

Add support of nested paths

grundic opened this issue · 3 comments

This is related to incorrectly created #7.
Can you add possibility to specify field disposition in case it's not at root level? Here is small example:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from simplemodels.fields import CharField, IntegerField
from simplemodels.models import Document


class User(Document):
    name = CharField()
    salary = IntegerField()


data = {
    'name': 'John Smith',
    'data': {
        'salary': 100500
    }
}


if __name__ == '__main__':
    user = User.create(data)
    print(user)

I would like to be able to specify in User model that the salary is nested under data path. And it should be possible to specify nested path. List of strings or usual uri should work fine:

class User(Document):
    name = CharField()
    salary = IntegerField(nested=['data'])

There one things to consider, though: should the configuration count the field itself, or only the nested path: ['data'] vs ['data', 'salary']. The latte less obvious, but let rename fields. But I would say that for that behaviour there should be another configuration option.

Might be a good feature. I will ponder about design of this. No promises so far, but pull requests most welcome

UPD:
From my pov it should be a separate field type. It basically DictField field with custom getter + validation. To many specifics to extend current fields.

But what if the field is not a dictionary? It could be list of fields or other document, just nested deeper in the tree.
Right now it's possible to achieve the same behaviour using intermediate document:

from simplemodels.fields import CharField, ListField, DocumentField
from simplemodels.models import Document


class Comment(Document):
    body = CharField()


class User(Document):
    class _Data(Document):
        comments = ListField([Comment])

    name = CharField()
    data = DocumentField(_Data)


data = {
    'name': 'John Smith',
    'data': {
        'comments': [
            {'body': 'comment #1'},
            {'body': 'seconds comment'},
            {'body': 'one more comment'},
        ]
    }
}

if __name__ == '__main__':
    user = User.create(data)
    print(user.name)
    for comment in user.data.comments:
        print(comment)

But there other reasons, why I would prefer to have it described like this:

from simplemodels.fields import CharField, ListField, DocumentField
from simplemodels.models import Document


class Comment(Document):
    body = CharField()


class User(Document):    
    name = CharField()
    comments = ListField([Comment], nested=['data'])

ok, now I see your point