Exemplo n.º 1
0
    def from_query_result(cls, model, doc, nested_doc=False):
        parent_key = None
        if nested_doc:
            doc_dict = doc
        elif doc:
            parent_key = utils.get_parent_doc(doc.reference.path)
            if doc.to_dict():
                doc_dict = doc.to_dict()
            else:
                return None
        else:
            return None

        # instance values is changed according to firestore
        # so mark it modified this will help later for figuring
        # out the updated fields when need to update this document
        setattr(model, '_instance_modified', True)
        for k, v in doc_dict.items():
            field = model._meta.get_field_by_column_name(k)
            # if missing field setting is set to "ignore" then
            # get_field_by_column_name return None So, just skip this field
            if field is None:
                continue
            # Check if it is Reference field
            if isinstance(field, ReferenceField):
                val = ReferenceFieldWrapper.from_doc_ref(
                    model, field, field.field_value(v))
            elif isinstance(field, NestedModel):
                nested_doc_val = field.field_value(v)
                if nested_doc_val:
                    val = NestedModelWrapper.from_model_dict(
                        field, nested_doc_val)
                else:
                    val = None
            else:
                val = field.field_value(v)
            setattr(model, field.name, val)

        # If parent key is None but here is parent key from doc then set the parent for this model
        # This is case when you filter the documents parent key not auto set just set it
        if not model.parent and parent_key is not None:
            model.parent = parent_key

        # If it is not nested model then set the id for this model
        if not nested_doc:
            # When getting document attach the IDField if there is no user specify
            # it will prevent to generate new id everytime when document save
            # For more information see issue #45 https://github.com/octabytes/FireO/issues/45
            if model._meta.id is None:
                model._meta.id = ('id', IDField())

            setattr(model, '_id', doc.id)
            # save the firestore reference doc so that further actions can be performed (i.e. collections())
            model._meta.set_reference_doc(doc.reference)
            # even though doc.reference currently points to self, there is no guarantee this will be true
            # in the future, therefore we should store the create time and update time separate.
            model._meta._firestore_create_time = doc.create_time
            model._meta._firestore_update_time = doc.update_time
        return model
Exemplo n.º 2
0
def test_simple_create_get_direct_child_model():
    p = DirectParentModel.collection.create(name="Direct_Parent_Model")
    c = DirectChildModel.collection.create(parent=p.key, age=26)

    assert utils.get_parent_doc(c.key) == p.key

    child = DirectChildModel.collection.get(c.key)

    assert child.age == 26
def test_parent_create_id():
    p = AbParent1.collection.create(id='test_parent_create_id',
                                    name='test_parent')
    c = AbChild1.collection.create(parent=p.key,
                                   id='child_create_id',
                                   address="child_address")

    assert utils.get_parent_doc(c.key) == p.key
    assert c.id == 'child_create_id'
    assert p.id == 'test_parent_create_id'
def test_parent_create_with_obj():
    p = AbParent()
    p.name = 'test_parent'
    p.save()

    c = AbChild(parent=p.key)
    c.address = 'child_address'
    c.save()

    assert utils.get_parent_doc(c.key) == p.key
def test_parent_create_diff_name():
    p = AbParent2.collection.create(p_id='test_parent_create_id',
                                    name='test_parent')
    c = AbChild2.collection.create(parent=p.key,
                                   c_id='child_create_id',
                                   address="child_address")

    assert utils.get_parent_doc(c.key) == p.key
    assert c.c_id == 'child_create_id'
    assert p.p_id == 'test_parent_create_id'
    assert c.id is None
    assert p.id is None
Exemplo n.º 6
0
def test_parent_cursor_fetch():
    # Sample data
    p = CursorParentFetch.collection.create(name='Some Name')
    parent_key = p.key

    for n in range(10):
        ch = CursorChildFetch(parent=parent_key)
        ch.age = n
        ch.save()

    childs = CursorChildFetch.collection.order('created_on').fetch(3)

    for c in childs:
        assert utils.get_parent_doc(c.key) == parent_key
        assert c.age in [1, 2, 3]

    c = childs.cursor

    childs = CursorChildFetch.collection.cursor(c).fetch(3)

    for c in childs:
        assert utils.get_parent_doc(c.key) == parent_key
        assert c.age in [4, 5, 6]
def test_parent_create_with_id():
    p = AbParent1()
    p.id = 'test_parent_create_id'
    p.name = 'test_parent'
    p.save()

    c = AbChild1(parent=p.key)
    c.id = 'child_create_id'
    c.address = 'child_address'
    c.save()

    assert utils.get_parent_doc(c.key) == p.key
    assert c.id == 'child_create_id'
    assert p.id == 'test_parent_create_id'
Exemplo n.º 8
0
def test_parent_filter_update():
    p = FilterUpdateParent.collection.create(name="Some Name")
    parent_key = p.key

    c = FilterUpdateChild(parent=parent_key)
    c.name = 'Azeem'
    c.age = 26
    c.save()

    c = FilterUpdateChild.collection.parent(parent_key).filter(
        'name', '==', 'Azeem').get()
    assert utils.get_parent_doc(c.key) == parent_key
    print(c.key)
    c.age = 27
    c.update()

    child_key = c.key

    c = FilterUpdateChild.collection.get(child_key)

    assert c.key == child_key
    assert utils.get_parent_doc(c.key) == parent_key
    assert c.name == 'Azeem'
    assert c.age == 27
Exemplo n.º 9
0
 def __init__(self, model_cls, key):
     super().__init__(model_cls)
     super().set_collection_path(key=key)
     self.model = model_cls()
     # set parent to this model if any
     self.model.parent = utils.get_parent_doc(key)
     # Attach key to this model for updating this model
     # Purpose of attaching this key is user can update
     # this model after getting it
     #
     # For example:
     #   u = User.collection.get(user_key)
     #   u.name = "Updated Name"
     #   u.update()
     self.model.update_doc = key
     self.id = utils.get_id(key)
Exemplo n.º 10
0
def test_parent_create_with_obj_diff_name():
    p = AbParent2()
    p.p_id = 'test_parent_create_id'
    p.name = 'test_parent'
    p.save()

    c = AbChild2(parent=p.key)
    c.c_id = 'child_create_id'
    c.address = 'child_address'
    c.save()

    assert utils.get_parent_doc(c.key) == p.key
    assert c.c_id == 'child_create_id'
    assert p.p_id == 'test_parent_create_id'
    assert c.id is None
    assert p.id is None
Exemplo n.º 11
0
    def from_query_result(cls, model, doc, nested_doc=False):
        parent_key = None
        if nested_doc:
            doc_dict = doc
        elif doc:
            parent_key = utils.get_parent_doc(doc.reference.path)
            if doc.to_dict():
                doc_dict = doc.to_dict()
            else:
                return None
        else:
            return None

        # instance values is changed according to firestore
        # so mark it modified this will help later for figuring
        # out the updated fields when need to update this document
        setattr(model, '_instance_modified', True)
        for k, v in doc_dict.items():
            field = model._meta.get_field_by_column_name(k)
            # if missing field setting is set to "ignore" then
            # get_field_by_column_name return None So, just skip this field
            if field is None:
                continue
            # Check if it is Reference field
            if isinstance(field, ReferenceField):
                val = ReferenceFieldWrapper.from_doc_ref(
                    model, field, field.field_value(v))
            elif isinstance(field, NestedModel):
                nested_doc_val = field.field_value(v)
                if nested_doc_val:
                    val = NestedModelWrapper.from_model_dict(
                        field, nested_doc_val)
                else:
                    val = None
            else:
                val = field.field_value(v)
            setattr(model, field.name, val)

        # If parent key is None but here is parent key from doc then set the parent for this model
        # This is case when you filter the documents parent key not auto set just set it
        if not model.parent and parent_key is not None:
            model.parent = parent_key

        # If it is not nested model then set the id for this model
        if not nested_doc:
            setattr(model, '_id', doc.id)
        return model
Exemplo n.º 12
0
    def update(self, key=None, transaction=None, batch=None):
        """Update the existing document

        Update document without overriding it. You can update selected fields.

        Examples
        --------
        .. code-block:: python
            class User(Model):
                name = TextField()
                age = NumberField()

            u = User.collection.create(name="Azeem", age=25)
            id = u.id

            # update this
            user = User.collection.get(id)
            user.name = "Arfan"
            user.update()

            print(user.name)  # Arfan
            print(user.age)  # 25

        Parameters
        ----------
        key: str
            Key of document which is going to update this is optional you can also set
            the update_doc explicitly

        transaction:
            Firestore transaction

        batch:
            Firestore batch writes
        """

        # Check doc key is given or not
        if key:
            self._update_doc = key

        # make sure update doc in not None
        if self._update_doc is not None and '@temp_doc_id' not in self._update_doc:
            # set parent doc from this updated document key
            self.parent = utils.get_parent_doc(self._update_doc)
            # Get id from key and set it for model
            setattr(self, '_id', utils.get_id(self._update_doc))
            # Add the temp id field if user is not specified any
            if self._id is None and self.id:
                setattr(self._meta, 'id', ('id', fields.IDField()))
        elif self._update_doc is None and '@temp_doc_id' in self.key:
            raise InvalidKey(
                f'Invalid key to update model "{self.__class__.__name__}" ')

        # Get the updated fields
        updated_fields = {}
        for k, v in self._get_fields().items():
            if k in self._field_changed:
                updated_fields[k] = v
            # Get nested fields if any
            # Nested model store as dict in firestore so check values type is dict
            if type(v) is dict:
                # nested field name and value
                for name, value in v.items():
                    if name in self._field_changed:
                        # create the name with parent field name and child name
                        # For example:
                        #   class User(Model):
                        #       address = TextField()
                        #   class Student(Model):
                        #       age = NumberField()
                        #       user = NestedModel(User)
                        #
                        # Then the field name for nested model will be "user.address"
                        updated_fields[k + "." + name] = value
        # pass the model instance if want change in it after save, fetch etc operations
        # otherwise it will return new model instance
        return self.__class__.collection._update(self,
                                                 transaction=transaction,
                                                 batch=batch,
                                                 **updated_fields)
Exemplo n.º 13
0
def test_parent_create_get():
    p = AbParent.collection.create(name='test_parent')
    c = AbChild.collection.create(parent=p.key, address="child_address")

    assert utils.get_parent_doc(c.key) == p.key