Найти - Пользователи
Полная версия: Простая библиотека для создания моделей
Начало » Web » Простая библиотека для создания моделей
1
anzor.khoutov
Приветствую.

Вопрос на авось - можете ли подсказать библиотеку для создания примитивных моделей для использования в качестве примера для архитектурного решения. Идеально бы - на базе asyncmongo.
Из интересного нашел пока только https://github.com/namlook/MongoLite/ для pymongo.

Спасибо.
zheromo
Из интересного mongoengine

Из примтивного могу привсти свой код:
# -*- coding: utf-8 -*-
from livestreet.models.config import g
__all__ = (
    "Property",
    "KeyProperty",
    "RelationProperty",
    "IndexProperty",
    "ModelMeta",
    "Model",
)
class BaseProperty(object):
    name = None
    def __get__(self, model_instance, owner=None):
        raise AttributeError, "Cann't get attribute."
    def __set__(self, instance, value):
        raise AttributeError, "Cann't set attribute."
    def set_name(self, name):
        self.name = name
class Property(BaseProperty):
    def __init__(self, set_function, default=None, required=False):
        self.name = None
        self.set_function = set_function
        self.default = default
        self.required = required
    def __get__(self, model_instance, owner=None):
        return self.name in model_instance._data and model_instance._data[self.name] or self.get_default(model_instance)
    def __set__(self, model_instance, value):
        model_instance._data[self.name] = self.set_function(value)
    def get_default(self, model_instance):
        if self.required:
            raise AttributeError, "Required attribute `%s`." % self.name
        value = callable(self.default) and self.default() or self.default
        model_instance._data[self.name] = value
        return value
    def __delete__(self, model_instance):
        del model_instance._data[self.name]
class IndexProperty(BaseProperty):
    def __init__(self, key_or_list, unique=False):
        self.key_or_list = key_or_list
        self.unique = unique
    @property
    def kwargs(self):
        return {
            'key_or_list': self.key_or_list,
            'name': self.name,
            'unique': self.unique,
        }
class KeyProperty(Property):
    def __init__(self, set_function):
        super(KeyProperty, self).__init__(set_function, required=True)
class RelationProperty(Property):
    def __init__(self, model=None, default=None, required=False):
        model = model or 'any'
        if model in ['self', 'any']:
            pass
        elif not issubclass(model, Model):
            raise AttributeError, 'Must be a model subclass.'
        super(RelationProperty, self).__init__(model, default, required)
    def __get__(self, model_instance, owner=None):
        return self.name in model_instance._rel and model_instance._rel[self.name] or self.get_relation(model_instance)
    def get_relation(self, model_instance):
        value = super(RelationProperty, self).__get__(model_instance)
        if value:
            value = g.config.backend.get_relation(model_instance.__class__, value)
        model_instance._rel[self.name] = value
        return value
    def __set__(self, model_instance, value):
        if not (value is None or isinstance(value, Model)):
            raise AttributeError, 'Must be a Model instance.'
        model_instance._rel[self.name] = value
        if value:
            value = g.config.backend.set_relation(value.__class__, value)
        model_instance._data[self.name] = value
class ModelMeta(type):
    MODELS = {}
    def __new__(mcs, name, bases, attrs):
        def get_properties(model):
            fields = []
            indexes = []
            set_pk_name = False
            for name in model.__dict__.keys():
                property = model.__dict__[name]
                if isinstance(property, BaseProperty):
                    if not property.name:
                        property.set_name(name)
                    if issubclass(model, Model) and isinstance(property, KeyProperty):
                        if set_pk_name:
                            raise ValueError, "More than one key property."
                        model.pk_name, set_pk_name = name, True
                    if isinstance(property, IndexProperty):
                        indexes.append(property.kwargs)
                    else:
                        fields.append(property)
            for cls in model.mro():
                if cls == model or cls.__name__ == 'object':
                    continue
                _fields, _indexes = get_properties(cls)
                fields.extend(_fields)
                indexes.extend(_indexes)
            return fields, indexes
        model = super(ModelMeta, mcs).__new__(mcs, name, bases, attrs)
        meta = model._meta and model._meta.copy() or {}
        name = meta.get('name', model.__name__)
        if name != 'Model':
            if name in mcs.MODELS:
                raise ValueError, "Model with name `%s` already registered." % name
            mcs.MODELS[name] = model
            meta['model'] = name
            _fields, _indexes = get_properties(model)
            meta['fields'] = _fields
            meta['indexes'] = _indexes
            model._meta = meta
        return model
    @classmethod
    def factory(mcs, obj):
        model = mcs.MODELS[obj['_model']]
        return model.create(obj)
class Model(object):
    pk_name = None
    __metaclass__ = ModelMeta
    __collection__ = None
    _data = None
    _meta = None
    _new = True
    def __init__(self, **initial):
        self._rel = {}
        self._data = {}
        for k, v in initial.iteritems():
            setattr(self, k, v)
    @classmethod
    def create(cls, data):
        instance = cls()
        instance._new, instance._data = False, data
        return instance
    @property
    def id(self):
        # TODO to backend
        return self._data.get(self.pk_name, self._data.get('_id'))
    @property
    def key(self):
        return self.backend.set_relation(self.__class__, self)
    @property
    def backend(self):
        return g.config.backend
    @property
    def fields(self):
        for field in self._meta['fields']:
            yield field
    def __repr__(self):
        return '<Model instance %r>' % self._data
    def __eq__(self, other):
        return isinstance(other, Model) and self.id == other.id
    def __ne__(self, other):
        return not self == other
    def get_backend_data(self):
        data = {}
        for field in self._meta['fields']:
            data[field.name] = field.to_db(self)
        return data
    @classmethod
    def get(cls, id=None, **kwargs):
        for k in kwargs.keys():
            if isinstance(kwargs[k], Model):
                kwargs[k] = kwargs[k].key
        return g.config.backend.get(cls, id, **kwargs)
    def put(self):
        if self._new:
            for field in self._meta['fields']:
                if not field.name in self._data:
                    field.__get__(self)
        return self.backend.put(self)
    def delete(self):
        return self.backend.delete(self.__class__, self.id)
    @classmethod
    def filter(cls, **kwargs):
        for k in kwargs.keys():
            if isinstance(kwargs[k], Model):
                kwargs[k] = kwargs[k].key
        return g.config.backend.filter(cls, **kwargs)
    def incr(self, field_name, value=1):
        self.backend.incr(self, field_name, value)
class RelationModel(object):
    def __init__(self, model, rel):
        self.instance = None
        self.model = model
        self.rel = rel
    def __getattribute__(self, item):
        if self.instance is None:
            self.instance = g.config.backend.get_relation(self.model, item)
        return getattr(self.instance, item)
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB