Esempio n. 1
0
def django_instance_to_entity(connection, model, fields, raw, instance, check_null=True):
    from djangae.db.backends.appengine.indexing import special_indexes_for_column, get_indexer
    from djangae.db.backends.appengine import POLYMODEL_CLASS_ATTRIBUTE

    # uses_inheritance = False
    inheritance_root = get_top_concrete_parent(model)
    db_table = get_datastore_kind(inheritance_root)

    def value_from_instance(_instance, _field):
        value = get_prepared_db_value(connection, _instance, _field, raw)

        # If value is None, but there is a default, and the field is not nullable then we should populate it
        # Otherwise thing get hairy when you add new fields to models
        if value is None and _field.has_default() and not _field.null:
            value = connection.ops.value_for_db(_field.get_default(), _field)

        if check_null and (not _field.null and not _field.primary_key) and value is None:
            raise IntegrityError("You can't set %s (a non-nullable "
                                     "field) to None!" % _field.name)

        is_primary_key = False
        if _field.primary_key and _field.model == inheritance_root:
            is_primary_key = True

        return value, is_primary_key


    field_values = {}
    primary_key = None

    for field in fields:
        value, is_primary_key = value_from_instance(instance, field)
        if is_primary_key:
            primary_key = value
        else:
            field_values[field.column] = value

        # Add special indexed fields
        for index in special_indexes_for_column(model, field.column):
            indexer = get_indexer(field, index)
            values = indexer.prep_value_for_database(value, index)

            if values is None:
                continue

            if not hasattr(values, "__iter__"):
                values = [ values ]

            for v in values:
                column = indexer.indexed_column_name(field.column, v, index)
                if column in field_values:
                    if not isinstance(field_values[column], list):
                        field_values[column] = [ field_values[column], v ]
                    else:
                        field_values[column].append(v)
                else:
                    field_values[column] = v

    kwargs = {}
    if primary_key:
        if isinstance(primary_key, (int, long)):
            kwargs["id"] = primary_key
        elif isinstance(primary_key, basestring):
            if len(primary_key) > 500:
                warnings.warn("Truncating primary key that is over 500 characters. "
                              "THIS IS AN ERROR IN YOUR PROGRAM.",
                              RuntimeWarning)
                primary_key = primary_key[:500]

            kwargs["name"] = primary_key
        else:
            raise ValueError("Invalid primary key value")

    namespace = connection.settings_dict.get("NAMESPACE")
    entity = datastore.Entity(db_table, namespace=namespace, **kwargs)
    entity.update(field_values)

    classes = get_concrete_db_tables(model)
    if len(classes) > 1:
        entity[POLYMODEL_CLASS_ATTRIBUTE] = list(set(classes))

    return entity
Esempio n. 2
0
def django_instance_to_entities(connection, fields, raw, instance, check_null=True, model=None):
    """
        Converts a Django Model instance to an App Engine `Entity`

        Arguments:
            connection: Djangae appengine connection object
            fields: A list of fields to populate in the Entity
            raw: raw flag to pass to get_prepared_db_value
            instance: The Django model instance to convert
            check_null: Whether or not we should enforce NULL during conversion
            (throws an error if None is set on a non-nullable field)
            model: Model class to use instead of the instance one

        Returns:
            entity, [entity, entity, ...]

       Where the first result in the tuple is the primary entity, and the
       remaining entities are optionally descendents of the primary entity. This
       is useful for special indexes (e.g. contains)
    """

    from djangae.db.backends.appengine.indexing import special_indexes_for_column, get_indexer, IgnoreForIndexing
    from djangae.db.backends.appengine import POLYMODEL_CLASS_ATTRIBUTE

    model = model or type(instance)
    inheritance_root = get_top_concrete_parent(model)

    db_table = get_datastore_kind(inheritance_root)

    def value_from_instance(_instance, _field):
        value = get_prepared_db_value(connection, _instance, _field, raw)

        # If value is None, but there is a default, and the field is not nullable then we should populate it
        # Otherwise thing get hairy when you add new fields to models
        if value is None and _field.has_default() and not _field.null:
            value = connection.ops.value_for_db(_field.get_default(), _field)

        if check_null and (not _field.null and not _field.primary_key) and value is None:
            raise IntegrityError("You can't set %s (a non-nullable "
                                     "field) to None!" % _field.name)

        is_primary_key = False
        if _field.primary_key and _field.model == inheritance_root:
            is_primary_key = True

        return value, is_primary_key

    field_values = {}
    primary_key = None

    descendents = []
    fields_to_unindex = set()

    for field in fields:
        value, is_primary_key = value_from_instance(instance, field)
        if is_primary_key:
            primary_key = value
        else:
            field_values[field.column] = value

        # Add special indexed fields
        for index in special_indexes_for_column(model, field.column):
            indexer = get_indexer(field, index)

            unindex = False
            try:
                values = indexer.prep_value_for_database(value, index, model=model, column=field.column)
            except IgnoreForIndexing as e:
                # We mark this value as being wiped out for indexing
                unindex = True
                values = e.processed_value

            if not hasattr(values, "__iter__"):
                values = [values]

            # If the indexer returns additional entities (instead of indexing a special column)
            # then just store those entities
            if indexer.PREP_VALUE_RETURNS_ENTITIES:
                descendents.extend(values)
            else:
                for i, v in enumerate(values):
                    column = indexer.indexed_column_name(field.column, v, index)

                    if unindex:
                        fields_to_unindex.add(column)
                        continue

                    # If the column already exists in the values, then we convert it to a
                    # list and append the new value
                    if column in field_values:
                        if not isinstance(field_values[column], list):
                            field_values[column] = [field_values[column], v]
                        else:
                            field_values[column].append(v)
                    else:
                        # Otherwise we just set the column to the value
                        field_values[column] = v

    kwargs = {}
    if primary_key:
        if isinstance(primary_key, six.integer_types):
            kwargs["id"] = primary_key
        elif isinstance(primary_key, six.string_types):
            kwargs["name"] = primary_key
        else:
            raise ValueError("Invalid primary key value")

    namespace = connection.settings_dict.get("NAMESPACE")
    entity = datastore.Entity(db_table, namespace=namespace, **kwargs)
    entity.update(field_values)

    if fields_to_unindex:
        entity._properties_to_remove = fields_to_unindex

    classes = get_concrete_db_tables(model)
    if len(classes) > 1:
        entity[POLYMODEL_CLASS_ATTRIBUTE] = list(set(classes))

    return entity, descendents
Esempio n. 3
0
def django_instance_to_entities(connection,
                                fields,
                                raw,
                                instance,
                                check_null=True,
                                model=None):
    """
        Converts a Django Model instance to an App Engine `Entity`

        Arguments:
            connection: Djangae appengine connection object
            fields: A list of fields to populate in the Entity
            raw: raw flag to pass to get_prepared_db_value
            instance: The Django model instance to convert
            check_null: Whether or not we should enforce NULL during conversion
            (throws an error if None is set on a non-nullable field)
            model: Model class to use instead of the instance one

        Returns:
            entity, [entity, entity, ...]

       Where the first result in the tuple is the primary entity, and the
       remaining entities are optionally descendents of the primary entity. This
       is useful for special indexes (e.g. contains)
    """

    from djangae.db.backends.appengine.indexing import special_indexes_for_column, get_indexer, IgnoreForIndexing
    from djangae.db.backends.appengine import POLYMODEL_CLASS_ATTRIBUTE

    model = model or type(instance)
    inheritance_root = get_top_concrete_parent(model)

    db_table = get_datastore_kind(inheritance_root)

    def value_from_instance(_instance, _field):
        value = get_prepared_db_value(connection, _instance, _field, raw)

        # If value is None, but there is a default, and the field is not nullable then we should populate it
        # Otherwise thing get hairy when you add new fields to models
        if value is None and _field.has_default() and not _field.null:
            value = connection.ops.value_for_db(_field.get_default(), _field)

        if check_null and (not _field.null
                           and not _field.primary_key) and value is None:
            raise IntegrityError("You can't set %s (a non-nullable "
                                 "field) to None!" % _field.name)

        is_primary_key = False
        if _field.primary_key and _field.model == inheritance_root:
            is_primary_key = True

        return value, is_primary_key

    field_values = {}
    primary_key = None

    descendents = []
    fields_to_unindex = set()

    for field in fields:
        value, is_primary_key = value_from_instance(instance, field)
        if is_primary_key:
            primary_key = value
        else:
            field_values[field.column] = value

        # Add special indexed fields
        for index in special_indexes_for_column(model, field.column):
            indexer = get_indexer(field, index)

            unindex = False
            try:
                values = indexer.prep_value_for_database(value,
                                                         index,
                                                         model=model,
                                                         column=field.column)
            except IgnoreForIndexing as e:
                # We mark this value as being wiped out for indexing
                unindex = True
                values = e.processed_value

            if not hasattr(values, "__iter__"):
                values = [values]

            # If the indexer returns additional entities (instead of indexing a special column)
            # then just store those entities
            if indexer.PREP_VALUE_RETURNS_ENTITIES:
                descendents.extend(values)
            else:
                for i, v in enumerate(values):
                    column = indexer.indexed_column_name(
                        field.column, v, index)

                    if unindex:
                        fields_to_unindex.add(column)
                        continue

                    # If the column already exists in the values, then we convert it to a
                    # list and append the new value
                    if column in field_values:
                        if not isinstance(field_values[column], list):
                            field_values[column] = [field_values[column], v]
                        else:
                            field_values[column].append(v)
                    else:
                        # Otherwise we just set the column to the value
                        field_values[column] = v

    kwargs = {}
    if primary_key:
        if isinstance(primary_key, six.integer_types):
            kwargs["id"] = primary_key
        elif isinstance(primary_key, six.string_types):
            kwargs["name"] = primary_key
        else:
            raise ValueError("Invalid primary key value")

    namespace = connection.settings_dict.get("NAMESPACE")
    entity = datastore.Entity(db_table, namespace=namespace, **kwargs)
    entity.update(field_values)

    if fields_to_unindex:
        entity._properties_to_remove = fields_to_unindex

    classes = get_concrete_db_tables(model)
    if len(classes) > 1:
        entity[POLYMODEL_CLASS_ATTRIBUTE] = list(set(classes))

    return entity, descendents
Esempio n. 4
0
def django_instance_to_entity(connection, model, fields, raw, instance, check_null=True):
    # uses_inheritance = False
    inheritance_root = get_top_concrete_parent(model)
    db_table = get_datastore_kind(inheritance_root)

    def value_from_instance(_instance, _field):
        value = get_prepared_db_value(connection, _instance, _field, raw)

        # If value is None, but there is a default, and the field is not nullable then we should populate it
        # Otherwise thing get hairy when you add new fields to models
        if value is None and _field.has_default() and not _field.null:
            value = connection.ops.value_for_db(_field.get_default(), _field)

        if check_null and (not _field.null and not _field.primary_key) and value is None:
            raise IntegrityError("You can't set %s (a non-nullable "
                                     "field) to None!" % _field.name)

        is_primary_key = False
        if _field.primary_key and _field.model == inheritance_root:
            is_primary_key = True

        return value, is_primary_key


    field_values = {}
    primary_key = None

    for field in fields:
        value, is_primary_key = value_from_instance(instance, field)
        if is_primary_key:
            primary_key = value
        else:
            field_values[field.column] = value

        # Add special indexed fields
        for index in special_indexes_for_column(model, field.column):
            indexer = REQUIRES_SPECIAL_INDEXES[index.split('__')[0]] # Indexes can be named regex__aaa, hence splitting by __
            values = indexer.prep_value_for_database(value, index)

            if values is None:
                continue

            if not hasattr(values, "__iter__"):
                values = [ values ]

            for v in values:
                column = indexer.indexed_column_name(field.column, v, index)
                if column in field_values:
                    if not isinstance(field_values[column], list):
                        field_values[column] = [ field_values[column], v ]
                    else:
                        field_values[column].append(v)
                else:
                    field_values[column] = v

    kwargs = {}
    if primary_key:
        if isinstance(primary_key, (int, long)):
            kwargs["id"] = primary_key
        elif isinstance(primary_key, basestring):
            if len(primary_key) > 500:
                warnings.warn("Truncating primary key that is over 500 characters. "
                              "THIS IS AN ERROR IN YOUR PROGRAM.",
                              RuntimeWarning)
                primary_key = primary_key[:500]

            kwargs["name"] = primary_key
        else:
            raise ValueError("Invalid primary key value")

    entity = datastore.Entity(db_table, **kwargs)
    entity.update(field_values)

    classes = get_concrete_db_tables(model)
    if len(classes) > 1:
        entity[POLYMODEL_CLASS_ATTRIBUTE] = list(set(classes))

    return entity