示例#1
0
class MongoModel(
        with_metaclass(TopLevelMongoModelMetaclass, TopLevelMongoModel)):
    """Base class for all top-level models.

    A MongoModel definition typically includes a number of field instances
    and possibly a ``Meta`` class attribute that provides metadata or settings
    specific to the model.

    MongoModels can be instantiated either with positional or keyword arguments.
    Positional arguments are bound to the fields in the order the fields are
    defined on the model. Keyword argument names are the same as the names of
    the fields::

        from pymongo.read_preferences import ReadPreference

        class User(MongoModel):
            email = fields.EmailField(primary_key=True)
            name = fields.CharField()

            class Meta:
                # Read from secondaries.
                read_preference = ReadPreference.SECONDARY

        # Instantiate User using positional arguments:
        jane = User('*****@*****.**', 'Jane')
        # Keyword arguments:
        roy = User(name='Roy', email='*****@*****.**')

    Note that :func:`~pymodm.connection.connect` has to be called (defining the
    respective connection alias, if any) before any :class:`~pymodm.MongoModel`
    can be used with that alias. If ``indexes`` is defined on ``Meta``, then
    this has to be before the MongoModel class is evaluated.

    .. _metadata-attributes:

    The following metadata attributes are available:

      - `connection_alias`: The alias of the connection to use for the model.
      - `collection_name`: The name of the collection to use. By default, this
        is the same name as the model, converted to snake case.
      - `codec_options`: An instance of
        :class:`~bson.codec_options.CodecOptions` to use for reading and writing
        documents of this model type.
      - `final`: Whether to restrict inheritance on this model. If ``True``, the
        ``_cls`` field will not be stored in the document. ``False`` by
        default.
      - `cascade`: If ``True``, save all :class:`~pymodm.MongoModel` instances
        this object references when :meth:`~pymodm.MongoModel.save` is called
        on this object.
      - `read_preference`: The :class:`~pymongo.read_preferences.ReadPreference`
        to use when reading documents.
      - `read_concern`: The :class:`~pymongo.read_concern.ReadConcern` to use
        when reading documents.
      - `write_concern`: The :class:`~pymongo.write_concern.WriteConcern` to use
        for write operations.
      - `indexes`: This is a list of :class:`~pymongo.operations.IndexModel`
        instances that describe the indexes that should be created for this
        model. Indexes are created when the class definition is evaluated.
      - `ignore_unknown_fields`: If ``True``, fields that aren't defined in the
        model will be ignored when parsing documents from MongoDB, such as in
        :meth:`~pymodm.MongoModel.from_document`. By default, unknown fields
        will cause a ``ValueError`` to be raised. Note that with this option
        enabled, calling :meth:`~pymodm.MongoModel.save` will erase these
        fields for that model instance.

    .. note:: Creating an instance of MongoModel does not create a document in
              the database.

    """
    pass
示例#2
0
class EmbeddedMongoModel(with_metaclass(MongoModelMetaclass, MongoModelBase)):
    """Base class for models that represent embedded documents."""
    pass
示例#3
0
class MongoModel(with_metaclass(TopLevelMongoModelMetaclass, MongoModelBase)):
    """Base class for all top-level models.

    A MongoModel definition typically includes a number of field instances
    and possibly a ``Meta`` class attribute that provides metadata or settings
    specific to the model.

    MongoModels can be instantiated either with positional or keyword arguments.
    Positional arguments are bound to the fields in the order the fields are
    defined on the model. Keyword argument names are the same as the names of
    the fields::

        from pymongo.read_preferences import ReadPreference

        class User(MongoModel):
            email = fields.EmailField(primary_key=True)
            name = fields.CharField()

            class Meta:
                # Read from secondaries.
                read_preference = ReadPreference.SECONDARY

        # Instantiate User using positional arguments:
        jane = User('*****@*****.**', 'Jane')
        # Keyword arguments:
        roy = User(name='Roy', email='*****@*****.**')

    Note that :func:`~pymodm.connection.connect` has to be called (defining the
    respective connection alias, if any) before any :class:`~pymodm.MongoModel`
    can be used with that alias. If ``indexes`` is defined on ``Meta``, then
    this has to be before the MongoModel class is evaluated.

    .. _metadata-attributes:

    The following metadata attributes are available:

      - `connection_alias`: The alias of the connection to use for the moel.
      - `collection_name`: The name of the collection to use. By default, this
        is the same name as the model, converted to snake case.
      - `codec_options`: An instance of
        :class:`~bson.codec_options.CodecOptions` to use for reading and writing
        documents of this model type.
      - `final`: Whether to restrict inheritance on this model. If ``True``, the
        ``_cls`` field will not be stored in the document. ``False`` by
        default.
      - `cascade`: If ``True``, save all :class:`~pymodm.MongoModel` instances
        this object references when :meth:`~pymodm.MongoModel.save` is called
        on this object.
      - `read_preference`: The :class:`~pymongo.read_preferences.ReadPreference`
        to use when reading documents.
      - `read_concern`: The :class:`~pymongo.read_concern.ReadConcern` to use
        when reading documents.
      - `write_concern`: The :class:`~pymongo.write_concern.WriteConcern` to use
        for write operations.
      - `indexes`: This is a list of :class:`~pymongo.operations.IndexModel`
        instances that describe the indexes that should be created for this
        model. Indexes are created when the class definition is evaluated.

    .. note:: Creating an instance of MongoModel does not create a document in
              the database.

    """

    @classmethod
    def register_delete_rule(cls, related_model, related_field, rule):
        """Specify what to do when an instance of this class is deleted.

        :parameters:
          - `related_model`: The class that references this class.
          - `related_field`: The name of the field in ``related_model`` that
            references this class.
          - `rule`: The delete rule. See
            :class:`~pymodm.fields.ReferenceField` for details.

        """
        cls._mongometa.delete_rules[(related_model, related_field)] = rule

    @property
    def pk(self):
        """An alias for the primary key (called `_id` in MongoDB)."""
        if self._mongometa.pk is not None:
            return getattr(self, self._mongometa.pk.attname)

    @pk.setter
    def pk(self, value):
        if self._mongometa.pk is None:
            raise ValueError('No primary key set for %s'
                             % self._mongometa.object_name)
        setattr(self, self._mongometa.pk.attname, value)

    @property
    def _qs(self):
        if not hasattr(self, '__queryset'):
            self.__queryset = None
        if (self.__queryset is None and
                not self._mongometa.pk.is_undefined(self)):
            self.__queryset = self.__class__._default_manager.raw(
                {'_id': self._mongometa.pk.to_mongo(self.pk)})
        return self.__queryset

    def save(self, cascade=None, full_clean=True, force_insert=False):
        """Save this document into MongoDB.

        If there is no value for the primary key on this Model instance, the
        instance will be inserted into MongoDB. Otherwise, the entire document
        will be replaced with this version (upserting if necessary).

        :parameters:
          - `cascade`: If ``True``, all dereferenced MongoModels contained in
            this Model instance will also be saved.
          - `full_clean`: If ``True``, the
            :meth:`~pymodm.MongoModel.full_clean` method
            will be called before persisting this object.
          - `force_insert`: If ``True``, always do an insert instead of a
            replace. In this case, `save` will raise
            :class:`~pymongo.errors.DuplicateKeyError` if a document already
            exists with the same primary key.

        :returns: This object, with the `pk` property filled in if it wasn't
                  already.

        """
        cascade = validate_boolean_or_none('cascade', cascade)
        full_clean = validate_boolean('full_clean', full_clean)
        force_insert = validate_boolean('force_insert', force_insert)
        if full_clean:
            self.full_clean()
        if cascade or (self._mongometa.cascade and cascade is not False):
            for field_name in self:
                for referenced_object in self._find_referenced_objects(
                        getattr(self, field_name)):
                    referenced_object.save()
        if force_insert or self._mongometa.pk.is_undefined(self):
            result = self._mongometa.collection.insert_one(self.to_son())
            self.pk = result.inserted_id
        else:
            result = self._mongometa.collection.replace_one(
                {'_id': self._mongometa.pk.to_mongo(self.pk)},
                self.to_son(), upsert=True)
        return self

    def delete(self):
        """Delete this object from MongoDB."""
        self._qs.delete()

    def is_valid(self):
        """Return ``True`` if the data in this Model is valid.

        This method runs the
        :meth:`~pymodm.MongoModel.full_clean`
        method and returns ``True`` if no ValidationError was raised.

        """
        try:
            self.full_clean()
        except ValidationError:
            return False
        return True

    def refresh_from_db(self, fields=None):
        """Reload this object from the database, overwriting local field values.

        :parameters:
          - `fields`: An iterable of fields to reload. Defaults to all fields.

        .. warning:: This method will reload the object from the database,
           possibly with only a subset of fields. Calling
           :meth:`~pymodm.MongoModel.save` after this may revert or unset
           fields in the database.

        """
        fields = validate_list_tuple_or_none('fields', fields)
        if self._qs is None:
            raise OperationError('Cannot refresh from db before saving.')
        qs = self._qs.values()
        if fields:
            qs = qs.only(*fields)
        db_inst = qs.first()

        self._set_attributes(db_inst)
        return self

    def __eq__(self, other):
        if self.pk is not None:
            if isinstance(other, self.__class__) and other.pk is not None:
                return self.pk == other.pk
            elif isinstance(other, DBRef):
                return self.pk == other.id
        return self is other