def insert(self, data_list, return_id=False):
        opts = self.query.get_meta()
        unindexed_fields = get_model_indexes(self.query.model)['unindexed']
        unindexed_cols = [opts.get_field(name).column
                          for name in unindexed_fields]

        entity_list = []
        ancestor_keys = []
        for data in data_list:
            properties = {}
            kwds = {'unindexed_properties': unindexed_cols}
            for column, value in data.items():
                # The value will already be a db.Key, but the Entity
                # constructor takes a name or id of the key, and will
                # automatically create a new key if neither is given.
                if column == opts.pk.column:
                    if value is not None:
                        if isinstance(value, AncestorKey):
                            ancestor_keys.append(value)

                        kwds['id'] = value.id()
                        kwds['name'] = value.name()
                        kwds['parent'] = value.parent()

                # GAE does not store empty lists (and even does not allow
                # passing empty lists to Entity.update) so skip them.
                elif isinstance(value, (tuple, list)) and not len(value):
                    continue

                # Use column names as property names.
                else:
                    properties[column] = value

            entity = Entity(opts.db_table, **kwds)
            entity.update(properties)
            entity_list.append(entity)

        keys = Put(entity_list)
        if ancestor_keys and len(ancestor_keys) == len(keys):
            for ancestor_key, key in zip(ancestor_keys, keys):
                ancestor_key.key_id = key.id_or_name()

        return keys[0] if isinstance(keys, list) else keys