Форум сайта python.su
Приветствую.
Вопрос на авось - можете ли подсказать библиотеку для создания примитивных моделей для использования в качестве примера для архитектурного решения. Идеально бы - на базе asyncmongo.
Из интересного нашел пока только https://github.com/namlook/MongoLite/ для pymongo.
Спасибо.
Отредактировано anzor.khoutov (Ноя. 10, 2012 00:17:52)
Офлайн
Из интересного 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)
Офлайн