예제 #1
0
파일: model.py 프로젝트: bdragon300/koifish
    def __new__(cls, name, bases, attrs):
        if name in cls.models:
            raise ModelError("'{}' model is already defined in '{}'".format(
                name, cls.models[name].__module__))

        fields = {
            k: v
            for k, v in attrs.items()
            if not k.startswith('_') and isinstance(v, Field)
        }
        pk = None

        for base in bases:
            if hasattr(base, 'primary_key'):
                pk = getattr(base, 'primary_key') or pk

        pk = attrs.get('primary_key') or pk

        # Find primary key among fields if `primary_key` property has not explicitly set anywhere in model hierarchy
        if not pk:
            pks = list(k for k, v in attrs.items()
                       if isinstance(v, Field) and v.primary_key)
            if fields and len(pks) == 0:
                raise ModelError("No primary key in model '{}'".format(name))
            elif len(pks) > 1:
                raise ModelError(
                    "More than one field is primary key in model '{}'".format(
                        name))
            elif pks:
                attrs['primary_key'] = pks[0]

        attrs['_meta'] = weakref.proxy(cls)

        c = super(ModelMeta, cls).__new__(cls, name, bases, attrs)
        if name != 'BaseModel':
            cls.models[name] = c

        # Pass model class to each foreign field
        for k, v in fields.items():
            if isinstance(v, ForeignRel):
                attrs[k].init(c)
        for base in bases:
            bforeigns = list(
                k for k, v in base.__dict__.items()
                if not k.startswith('_') and isinstance(v, ForeignRel))
            for k in bforeigns:
                getattr(base, k).init(c)

        return c
예제 #2
0
파일: model.py 프로젝트: bdragon300/koifish
    def save(self):
        """
        Save the model
        :return: self
        """
        if self._deleted:
            raise ModelError('Cannot save already deleted record')

        # Raises ValidationError if validation failed
        if self._validate_on_write:
            self.validate()

        data = {k: self._data.get(v) for k, v in self._request_fields.items()}

        if self[self.primary_key] is None:
            res = self._impl_object.create(self.__class__, data)
        else:
            res = self._impl_object.update(self.__class__, data)

        # Update model with returned data if any
        # Reduce result dict according with fields since it may contain extra keys
        # Don't use `update` method since the data has a mapped value for fields with enums, while those method sets
        #  value as enum value
        if res is not None:
            res = {
                self._request_fields[k]: v
                for k, v in res.items() if k in self._request_fields
            }
            self._data = res

        return self
예제 #3
0
    def _related(self):
        """Related model class"""
        if self._my_model_cls is None:
            raise ModelError("Model not initialized")

        if self._to_model_cached is None:
            mdl_cls = self._my_model_cls._meta.models.get(
                self._to) if isinstance(self._to, str) else self._to
            if mdl_cls is not None:
                self._to_model_cached = mdl_cls
            else:
                raise ModelError(
                    "Model '{}' related from '{}' is not found".format(
                        self._to, self._my_model_cls.__name__))

        return self._to_model_cached
예제 #4
0
    def _get_to_field(self, to_model_cls):
        if self._my_model_cls is None:
            raise ModelError("Model not initialized")

        our_name = inflection.underscore(self._my_model_cls.__name__)
        our_pk = 'id'

        return our_name + '_' + our_pk
예제 #5
0
파일: model.py 프로젝트: bdragon300/koifish
    def delete(self):
        """
        Delete record. After deletion the model becomes read-only.
        :return: self
        """
        if self._deleted:
            raise ModelError('Record is already deleted')

        pk = self.primary_key
        pk_val = self._data[self._fields[pk]]

        if pk_val is None:
            raise ModelError('Primary key is not set')

        self._impl_object.delete(self.__class__, pk, pk_val)

        self._deleted = True

        return self
예제 #6
0
    def to_field(self):
        if self._to_field is None:
            f = self._get_to_field(self._related)
        else:
            f = self._to_field

        if not hasattr(self._related, f):
            raise ModelError("'{}' field does not exist in model '{}'".format(
                f, self._related.__name__))

        return f
예제 #7
0
파일: model.py 프로젝트: bdragon300/koifish
    def _get_impl(self, layer_class):
        """
        Try to get implementation class from given layer. If not found try to find it in default one. If not found again
        raise exception
        :param layer_class: layer class
        :raises ModelError: implementation class not found
        :return: implementation class
        """
        cls = self.__class__
        iobj = layer_class.get_impl(cls)
        if iobj is None and self._search_impl_in_default_layer:
            iobj = self._default_layer.get_impl(cls)

        if iobj is None:
            raise ModelError(
                "Cannot find implementation for '{}' in layers [{}, {}]".
                format(cls.__name__, layer_class.__name__,
                       self._default_layer.__name__))

        return iobj