Exemplo n.º 1
0
    def __init__(self, engine=None, **data):
        """A Model can be instantiated with keyword-arguments that
        have the same keys as the declared fields, it will make a new
        model instance that is ready to be persited in the database.

        DO NOT overwrite the __init__ method of your custom model.

        There are 2 possibilities of customization of your model in
        construction time:

        * Implement a `preprocess(self, data)` method in your model,
        this method takes the dictionary that has the
        keyword-arguments given to the constructor and should return a
        dictionary with that data "post-processed" This ORM provides
        the handy optional method `initialize` that is always called
        in the end of the constructor.

        * Implement the `initialize(self)` method that will be always
          called after successfully creating a new model instance.
        """
        Model = self.__class__
        module = Model.__module__
        name = Model.__name__
        columns = self.__columns__

        for key, value in data.items():
            data[key] = self.decrypt_attribute(key, value)

        preprocessed_data = self.preprocess(data)

        if not isinstance(preprocessed_data, dict):
            raise InvalidModelDeclaration(
                "The model `{0}` declares a preprocess method but "
                "it does not return a dictionary!".format(name))

        self.__data__ = preprocessed_data

        self.engine = engine

        for k, v in data.items():
            if k not in self.__columns__:
                msg = "{0} is not a valid column name for the model {2}.{1} ({3})"
                raise InvalidColumnName(
                    msg.format(k, name, module, sorted(columns.keys())))

            if callable(v):
                v = v()

            setattr(self, k, v)

        self.initialize()
Exemplo n.º 2
0
    def generate_query(self,
                       order_by=None,
                       limit_by=None,
                       offset_by=None,
                       **kw):
        """Queries the table with the given keyword-args and
        optionally a single order_by field."""
        query = self.model.table.select()
        for field, value in kw.items():
            if callable(value):
                value = value()

            if hasattr(self.model.table.c, field):
                query = query.where(
                    getattr(self.model.table.c, field) == value)
            elif '__' in field:
                field, modifier = field.split('__', 1)
                f = getattr(self.model.table.c, field)
                if modifier == 'startswith':
                    query = query.where(f.startswith(value))
                elif modifier == 'contains':
                    contains = f.contains(escape_query(value), escape='#')
                    query = query.where(contains)
                else:
                    msg = '"{}" is in invalid query modifier.'.format(modifier)
                    raise InvalidQueryModifier(msg)
            else:
                msg = 'The field "{}" does not exist.'.format(field)
                raise InvalidColumnName(msg)

        if isinstance(limit_by, (float, int)):
            query = query.limit(limit_by)

        if isinstance(offset_by, (float, int)):
            query = query.offset(offset_by)

        # Order the results
        db_order = db.desc
        if order_by:
            if order_by.startswith('+'):
                order_by = order_by[1:]
                db_order = db.asc
            elif order_by.startswith('-'):
                order_by = order_by[1:]

        query = query.order_by(
            db_order(
                getattr(self.model.table.c, order_by
                        or self.model.get_pk_name())))

        return query
Exemplo n.º 3
0
    def set(self, **kw):
        """Sets multiple fields, does not perform a save operation"""
        cols = self.__columns__.keys()
        pk_regex = re.compile(r"^{}_\d+$".format(self.get_pk_name))

        for name, value in kw.items():
            if pk_regex.match(name):
                continue

            if name not in cols:
                raise InvalidColumnName("{0}.{1}".format(self, name))
            setattr(self, name, value)
            self.__data__[name] = value

        return self