def it_can_fetch_data_from_the_underlying_model(self):
        DjangoModel = Mock(name="DjangoModel")
        mock_model = Mock()
        mock_model.id = 1
        DjangoModel.objects.get.return_value = mock_model

        manager = BackendManager('django')
        # The manager needs to know which model it connects to
        # This is normally done when the Document is created.
        manager._model = DjangoModel

        doc = Mock(name="mock_document", spec=Document)
        field = fields.NumberField()
        field.name = "id"
        doc.id = 1
        doc._context = {}
        doc._get_context.return_value = {}
        doc._meta.identifier = ["id"]
        doc._identifier_state.return_value = {"id": 1}
        doc._save.return_value = {"id": 1}
        doc._meta.local_fields = [field]

        # make sure we are working with correct expectations
        eq_(DjangoBackendManager, type(manager))
        eq_({'id': 1}, manager.fetch(doc))
        eq_([('objects.get', {'id': 1})], DjangoModel.method_calls)
    def it_calls_the_fetch_field_method_when_saving(self):
        DocModel = Mock()

        class Doc(Document):
            id = fields.NumberField()
            name = fields.StringField()

            class Meta:
                backend_type = 'django'
                model = DocModel

            def map_name_field(self):
                return "mapped_name"

        # prepare the django backend
        DocModel.DoesNotExist = Exception
        DocModel.objects.get.side_effect = DocModel.DoesNotExist
        mock_doc = Mock()
        DocModel.return_value = mock_doc

        # create and save the document
        doc = Doc({'id': 1, 'name': 'docname'})

        manager = BackendManager('django')
        manager._model = DocModel
        manager.save(doc)

        # The save should have set this attribute on the django model as
        # defined by the map_field method
        eq_(True, hasattr(mock_doc, 'mapped_name'))
        # and also have the attribute set to the right value
        eq_('docname', mock_doc.mapped_name)
    def it_can_save_data_to_the_underlying_model(self):
        DjangoModel = Mock(name="DjangoModel")
        mock_model = Mock()
        DjangoModel.objects.get_or_create.return_value = (mock_model, False)

        manager = BackendManager("django")
        # The manager needs to know which model it connects to
        # This is normally done when the Document is created.
        manager._model = DjangoModel

        # make sure we are working with correct expectations
        eq_(DjangoBackendManager, type(manager))

        doc = Mock(name="mock_document", spec=Document)
        field = fields.NumberField()
        field.name = "id"
        doc.id = 1
        doc._context = {}
        doc._get_context.return_value = {}
        doc._meta.identifier = ["id"]
        doc._identifier_state.return_value = {"id": 1}
        doc._save.return_value = {"id": 1}
        doc._meta.local_fields = [field]

        # the manager.save() method doesn't return on success
        manager.save(doc)
        eq_([("objects.get", {"id": 1})], DjangoModel.method_calls)
    def it_can_return_a_django_m2m_relationship_as_collection(self):
        DjangoModel = Mock(name="DjangoModel")
        mock_model = Mock()
        mock_model.id = 1
        mock_model.get_absolute_url.return_value = "A"

        OtherModel = Mock(name="OtherMock")
        mock1 = Mock()
        mock1.id = 1
        mock1.get_absolute_url.return_value = "1"
        mock2 = Mock()
        mock2.id = 2
        mock2.get_absolute_url.return_value = "2"

        # This mocks a many2many relation ship, its not a queryset, just a list
        mock_model.others.all.return_value = [mock1, mock2]

        x = [mock2, mock1]

        def mock_side_effect(*args, **kwargs):
            return x.pop()

        OtherModel.objects.get.side_effect = mock_side_effect
        DjangoModel.objects.get.return_value = mock_model

        # Now create a simple document setup
        class OtherDoc(Document):
            id = fields.NumberField()

            class Meta:
                backend_type = "django"
                identifier = "id"
                model = OtherModel

        class OtherCollection(Collection):
            document = OtherDoc

        class Doc(Document):
            id = fields.NumberField()
            others = fields.CollectionField(OtherCollection)

            class Meta:
                backend_type = "django"
                identifier = "id"
                model = DjangoModel

        manager = BackendManager("django")
        # The manager needs to know which model it connects to
        # This is normally done when the Document is created.
        manager._model = DjangoModel

        # make sure we are working with correct expectations
        eq_(DjangoBackendManager, type(manager))

        doc = Doc({"id": 1})
        # doc.fetch()

        expected = {"id": 1, "others": [{"id": 1}, {"id": 2}]}
        eq_(expected, manager.fetch(doc))
    def it_can_delete_the_underlying_model_instance(self):
        DjangoModel = Mock(name="DjangoModel")
        mock_model = Mock()
        mock_model.id = 1
        DjangoModel.objects.get.return_value = mock_model

        manager = BackendManager('django')
        # The manager needs to know which model it connects to
        # This is normally done when the Document is created.
        manager._model = DjangoModel

        # make sure we are working with correct expectations
        eq_(DjangoBackendManager, type(manager))

        class Doc(Document):
            id = fields.NumberField()

            class Meta:
                backend_type = 'django'
                model = DjangoModel

        doc = Doc({'id': 1})

        manager.delete(doc)

        eq_([('objects.get', {'id': 1})], DjangoModel.method_calls)
        eq_([('delete',)], mock_model.method_calls)

        # If the model does not exist, nothing happens
        DjangoModel.reset_mock()
        mock_model.reset_mock()

        DjangoModel.DoesNotExist = Exception
        DjangoModel.objects.get.side_effect = DjangoModel.DoesNotExist

        manager.delete(doc)

        eq_([('objects.get', {'id': 1})], DjangoModel.method_calls)
        # no method of the model should have been called
        eq_([], mock_model.method_calls)