def __init__(self, retrieved_fields=None, loading_from_db=False, **kwargs): ''' :param retrieved_fields: The names of the fields returned when loading \ a partial object. This argument should not be explicitly set \ by subclasses :param \*\*kwargs: The values for all of the fields in the document. \ Any additional fields will raise a :class:`~mongoalchemy.document.ExtraValueException` and \ any missing (but required) fields will raise a :class:`~mongoalchemy.document.MissingValueException`. \ Both types of exceptions are subclasses of :class:`~mongoalchemy.document.DocumentException`. ''' self.partial = retrieved_fields is not None self.retrieved_fields = self.__normalize(retrieved_fields) # Mapping from attribute names to values. self._values = {} self.__extra_fields = {} cls = self.__class__ # Process the fields on the object fields = self.get_fields() for name, field in fields.items(): # print name if self.partial and field.db_field not in self.retrieved_fields: self._values[name] = Value(field, self, retrieved=False) elif name in kwargs: field = getattr(cls, name) value = kwargs[name] self._values[name] = Value(field, self, from_db=loading_from_db) field.set_value(self, value) elif field.auto: self._values[name] = Value(field, self, from_db=False) else: self._values[name] = Value(field, self, from_db=False) # Process any extra fields for k in kwargs: if k not in fields: if self.config_extra_fields == 'ignore': self.__extra_fields[k] = kwargs[k] else: raise ExtraValueException(k) self.__extra_fields_orig = dict(self.__extra_fields) # Validate defult sort if self.config_default_sort: for (name, direction) in self.config_default_sort: try: resolve_name(type(self), name) dirs = (1, -1, pymongo.ASCENDING, pymongo.DESCENDING) if direction not in dirs: m = 'Bad sort direction on %s: %s' % (name, direction) raise BadFieldSpecification(m) except FieldNotFoundException: raise BadFieldSpecification("Could not resolve field %s in" " config_default_sort" % name)
def __init__(self, retrieved_fields=None, loading_from_db=False, **kwargs): ''' :param retrieved_fields: The names of the fields returned when loading \ a partial object. This argument should not be explicitly set \ by subclasses :param \*\*kwargs: The values for all of the fields in the document. \ Any additional fields will raise a :class:`~mongoalchemy.document.ExtraValueException` and \ any missing (but required) fields will raise a :class:`~mongoalchemy.document.MissingValueException`. \ Both types of exceptions are subclasses of :class:`~mongoalchemy.document.DocumentException`. ''' self.partial = retrieved_fields is not None self.retrieved_fields = self.__normalize(retrieved_fields) # Mapping from attribute names to values. self._values = {} self.__extra_fields = {} cls = self.__class__ # Process the fields on the object fields = self.get_fields() for name, field in fields.iteritems(): # print name if self.partial and field.db_field not in self.retrieved_fields: self._values[name] = Value(field, self, retrieved=False) elif name in kwargs: field = getattr(cls, name) value = kwargs[name] self._values[name] = Value(field, self, from_db=loading_from_db) getattr(cls, name).set_value(self, kwargs[name]) elif field.auto: self._values[name] = Value(field, self, from_db=False) else: self._values[name] = Value(field, self, from_db=False) # Process any extra fields for k in kwargs: if k not in fields: if self.config_extra_fields == 'ignore': self.__extra_fields[k] = kwargs[k] else: raise ExtraValueException(k) self.__extra_fields_orig = dict(self.__extra_fields) # Validate defult sort if self.config_default_sort: for (name, direction) in self.config_default_sort: try: resolve_name(type(self), name) dirs = (1, -1, pymongo.ASCENDING, pymongo.DESCENDING) if direction not in dirs: m = 'Bad sort direction on %s: %s' % (name, direction) raise BadFieldSpecification(m) except FieldNotFoundException: raise BadFieldSpecification("Could not resolve field %s in" " config_default_sort" % name)
def __sort(self, qfield, direction): qfield = resolve_name(self.type, qfield) name = str(qfield) for n, _ in self._sort: if n == name: raise BadQueryException('Already sorting by %s' % name) self._sort.append((name, direction)) return self
def __hint(self, qfield, direction): qfield = resolve_name(self.type, qfield) name = str(qfield) for n, _ in self.hints: if n == name: raise BadQueryException('Already gave hint for %s' % name) self.hints.append((name, direction)) return self
def _atomic_generic_op(self, op, qfield, value): qfield = resolve_name(self.query.type, qfield) if op not in qfield.valid_modifiers: raise InvalidModifierException(qfield, op) if op not in self.update_data: self.update_data[op] = {} self.update_data[op][qfield.get_absolute_name()] = value return self
def _apply_dict(self, qe_dict): ''' Apply a query expression, updating the query object ''' for k, v in qe_dict.iteritems(): k = resolve_name(self.type, k) if not k in self.__query: self.__query[k] = v continue if not isinstance(self.__query[k], dict) or not isinstance(v, dict): raise BadQueryException('Multiple assignments to a field must all be dicts.') self.__query[k].update(**v)
def _atomic_list_op_multivalue(self, op, qfield, *value): qfield = resolve_name(self.query.type, qfield) if op not in qfield.valid_modifiers: raise InvalidModifierException(qfield, op) wrapped = [] for v in value: wrapped.append(qfield.get_type().item_type.wrap(v)) if op not in self.update_data: self.update_data[op] = {} self.update_data[op][qfield.get_absolute_name()] = value return self
def nin(self, qfield, *values): ''' Check to see that the value of ``qfield`` is not one of ``values`` :param qfield: Instances of :class:`mongoalchemy.query_expression.QueryExpression` :param values: Values should be python values which ``qfield`` \ understands ''' # TODO: make sure that this field represents a list qfield = resolve_name(self.type, qfield) self.filter(QueryExpression({ qfield : { '$nin' : [qfield.wrap_value(value) for value in values]}})) return self
def _apply_dict(self, qe_dict): ''' Apply a query expression, updating the query object ''' for k, v in qe_dict.iteritems(): k = resolve_name(self.type, k) if not k in self.__query: self.__query[k] = v continue if not isinstance(self.__query[k], dict) or not isinstance( v, dict): raise BadQueryException( 'Multiple assignments to a field must all be dicts.') self.__query[k].update(**v)
def sort(self, *sort_tuples): ''' pymongo-style sorting. Accepts a list of tuples. :param sort_tuples: varargs of sort tuples. ''' query = self for name, direction in sort_tuples: field = resolve_name(self.type, name) if direction in (ASCENDING, 1): query = query.ascending(field) elif direction in (DESCENDING, -1): query = query.descending(field) else: raise BadQueryException('Bad sort direction: %s' % direction) return query
def nin(self, qfield, *values): ''' Check to see that the value of ``qfield`` is not one of ``values`` :param qfield: Instances of :class:`mongoalchemy.query_expression.QueryExpression` :param values: Values should be python values which ``qfield`` \ understands ''' # TODO: make sure that this field represents a list qfield = resolve_name(self.type, qfield) self.filter( QueryExpression({ qfield: { '$nin': [qfield.wrap_value(value) for value in values] } })) return self
def fields(self, *fields): ''' Only return the specified fields from the object. Accessing a \ field that was not specified in ``fields`` will result in a \ :class:``mongoalchemy.document.FieldNotRetrieved`` exception being \ raised :param fields: Instances of :class:``mongoalchemy.query.QueryField`` specifying \ which fields to return ''' if self._fields == None: self._fields = set() for f in fields: f = resolve_name(self.type, f) self._fields.add(f) self._fields.add(self.type.mongo_id) return self
def filter_by(self, **filters): ''' Filter for the names in ``filters`` being equal to the associated values. Cannot be used for sub-objects since keys must be strings''' for name, value in filters.iteritems(): self.filter(resolve_name(self.type, name) == value) return self