Beispiel #1
0
    def _init_relations(cls):
        for app_name, app in cls.apps.items():
            for model_name, model in app.items():
                if model._meta._inited:
                    continue
                else:
                    model._meta._inited = True
                if not model._meta.table:
                    model._meta.table = model.__name__.lower()

                for field in model._meta.fk_fields:
                    field_object = model._meta.fields_map[field]
                    reference = field_object.model_name
                    related_app_name, related_model_name = reference.split('.')
                    related_model = cls.apps[related_app_name][
                        related_model_name]
                    field_object.type = related_model
                    backward_relation_name = field_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = '{}s'.format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))
                    fk_relation = fields.BackwardFKRelation(
                        model, '{}_id'.format(field))
                    setattr(related_model, backward_relation_name, fk_relation)
                    related_model._meta.filters.update(
                        get_backward_fk_filters(backward_relation_name,
                                                fk_relation))

                    related_model._meta.backward_fk_fields.add(
                        backward_relation_name)
                    related_model._meta.fetch_fields.add(
                        backward_relation_name)
                    related_model._meta.fields_map[
                        backward_relation_name] = fk_relation
                    related_model._meta.fields.add(backward_relation_name)

                for field in model._meta.m2m_fields:
                    field_object = model._meta.fields_map[field]
                    if field_object._generated:
                        continue

                    backward_key = field_object.backward_key
                    if not backward_key:
                        backward_key = '{}_id'.format(model._meta.table)
                        field_object.backward_key = backward_key

                    reference = field_object.model_name
                    related_app_name, related_model_name = reference.split('.')
                    related_model = cls.apps[related_app_name][
                        related_model_name]

                    field_object.type = related_model

                    backward_relation_name = field_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = '{}s'.format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))

                    if not field_object.through:
                        related_model_table_name = (
                            related_model._meta.table
                            if related_model._meta.table else
                            related_model.__name__.lower())

                        field_object.through = '{}_{}'.format(
                            model._meta.table,
                            related_model_table_name,
                        )

                    m2m_relation = fields.ManyToManyField(
                        '{}.{}'.format(app_name, model_name),
                        field_object.through,
                        forward_key=field_object.backward_key,
                        backward_key=field_object.forward_key,
                        related_name=field,
                        type=model)
                    m2m_relation._generated = True
                    setattr(
                        related_model,
                        backward_relation_name,
                        m2m_relation,
                    )
                    model._meta.filters.update(
                        get_m2m_filters(field, field_object))
                    related_model._meta.filters.update(
                        get_m2m_filters(backward_relation_name, m2m_relation))
                    related_model._meta.m2m_fields.add(backward_relation_name)
                    related_model._meta.fetch_fields.add(
                        backward_relation_name)
                    related_model._meta.fields_map[
                        backward_relation_name] = m2m_relation
                    related_model._meta.fields.add(backward_relation_name)
Beispiel #2
0
    def _init_relations(cls) -> None:
        def get_related_model(related_app_name: str, related_model_name: str):
            """
            Test, if app and model really exist. Throws a ConfigurationError with a hopefully
            helpful message. If successfull, returns the requested model.
            """
            try:
                return cls.apps[related_app_name][related_model_name]
            except KeyError:
                if related_app_name not in cls.apps:
                    raise ConfigurationError(
                        "No app with name '{}' registered.".format(
                            related_app_name))
                raise ConfigurationError(
                    "No model with name '{}' registered in app '{}'.".format(
                        related_model_name, related_app_name))

        def split_reference(reference: str) -> Tuple[str, str]:
            """
            Test, if reference follow the official naming conventions. Throws a
            ConfigurationError with a hopefully helpful message. If successfull,
            returns the app and the model name.
            """
            items = reference.split(".")
            if len(items) != 2:  # pragma: nocoverage
                raise ConfigurationError(
                    ("'%s' is not a valid model reference Bad Reference."
                     " Should be something like <appname>.<modelname>.") %
                    reference)

            return (items[0], items[1])

        for app_name, app in cls.apps.items():
            for model_name, model in app.items():
                if model._meta._inited:
                    continue
                model._meta._inited = True
                if not model._meta.table:
                    model._meta.table = model.__name__.lower()

                for field in model._meta.fk_fields:
                    fk_object = cast(fields.ForeignKeyField,
                                     model._meta.fields_map[field])
                    reference = fk_object.model_name
                    related_app_name, related_model_name = split_reference(
                        reference)
                    related_model = get_related_model(related_app_name,
                                                      related_model_name)

                    key_field = "{}_id".format(field)
                    key_fk_object = deepcopy(related_model._meta.pk)
                    key_fk_object.pk = False
                    key_fk_object.index = fk_object.index
                    key_fk_object.default = fk_object.default
                    key_fk_object.null = fk_object.null
                    key_fk_object.generated = fk_object.generated
                    key_fk_object.reference = fk_object
                    key_fk_object.description = fk_object.description
                    if fk_object.source_field:
                        key_fk_object.source_field = fk_object.source_field
                        fk_object.source_field = key_field
                    else:
                        fk_object.source_field = key_field
                        key_fk_object.source_field = key_field
                    model._meta.add_field(key_field, key_fk_object)

                    fk_object.type = related_model
                    backward_relation_name = fk_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = "{}s".format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))
                    fk_relation = fields.BackwardFKRelation(
                        model, "{}_id".format(field), fk_object.null,
                        fk_object.description)
                    related_model._meta.add_field(backward_relation_name,
                                                  fk_relation)

                for field in list(model._meta.m2m_fields):
                    m2m_object = cast(fields.ManyToManyField,
                                      model._meta.fields_map[field])
                    if m2m_object._generated:
                        continue

                    backward_key = m2m_object.backward_key
                    if not backward_key:
                        backward_key = "{}_id".format(model._meta.table)
                        if backward_key == m2m_object.forward_key:
                            backward_key = "{}_rel_id".format(
                                model._meta.table)
                        m2m_object.backward_key = backward_key

                    reference = m2m_object.model_name
                    related_app_name, related_model_name = split_reference(
                        reference)
                    related_model = get_related_model(related_app_name,
                                                      related_model_name)

                    m2m_object.type = related_model

                    backward_relation_name = m2m_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = m2m_object.related_name = "{}_through".format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))

                    if not m2m_object.through:
                        related_model_table_name = (
                            related_model._meta.table
                            if related_model._meta.table else
                            related_model.__name__.lower())

                        m2m_object.through = "{}_{}".format(
                            model._meta.table, related_model_table_name)

                    m2m_relation = fields.ManyToManyField(
                        "{}.{}".format(app_name, model_name),
                        m2m_object.through,
                        forward_key=m2m_object.backward_key,
                        backward_key=m2m_object.forward_key,
                        related_name=field,
                        type=model,
                        description=m2m_object.description,
                    )
                    m2m_relation._generated = True
                    model._meta.filters.update(
                        get_m2m_filters(field, m2m_object))
                    related_model._meta.add_field(backward_relation_name,
                                                  m2m_relation)
Beispiel #3
0
    def _init_relations(cls) -> None:
        for app_name, app in cls.apps.items():
            for model_name, model in app.items():
                if model._meta._inited:
                    continue
                else:
                    model._meta._inited = True
                if not model._meta.table:
                    model._meta.table = model.__name__.lower()

                for field in model._meta.fk_fields:
                    fk_object = cast(fields.ForeignKeyField,
                                     model._meta.fields_map[field])
                    reference = fk_object.model_name
                    related_app_name, related_model_name = reference.split(".")
                    related_model = cls.apps[related_app_name][
                        related_model_name]

                    key_field = "{}_id".format(field)
                    fk_object.source_field = key_field
                    key_fk_object = deepcopy(related_model._meta.pk)
                    key_fk_object.pk = False
                    key_fk_object.index = fk_object.index
                    key_fk_object.default = fk_object.default
                    key_fk_object.null = fk_object.null
                    key_fk_object.generated = fk_object.generated
                    key_fk_object.reference = fk_object
                    model._meta.add_field(key_field, key_fk_object)

                    fk_object.type = related_model
                    backward_relation_name = fk_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = "{}s".format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))
                    fk_relation = fields.BackwardFKRelation(
                        model, "{}_id".format(field))
                    related_model._meta.add_field(backward_relation_name,
                                                  fk_relation)

                for field in model._meta.m2m_fields:
                    m2m_object = cast(fields.ManyToManyField,
                                      model._meta.fields_map[field])
                    if m2m_object._generated:
                        continue

                    backward_key = m2m_object.backward_key
                    if not backward_key:
                        backward_key = "{}_id".format(model._meta.table)
                        m2m_object.backward_key = backward_key

                    reference = m2m_object.model_name
                    related_app_name, related_model_name = reference.split(".")
                    related_model = cls.apps[related_app_name][
                        related_model_name]

                    m2m_object.type = related_model

                    backward_relation_name = m2m_object.related_name
                    if not backward_relation_name:
                        backward_relation_name = m2m_object.related_name = "{}_through".format(
                            model._meta.table)
                    if backward_relation_name in related_model._meta.fields:
                        raise ConfigurationError(
                            'backward relation "{}" duplicates in model {}'.
                            format(backward_relation_name, related_model_name))

                    if not m2m_object.through:
                        related_model_table_name = (
                            related_model._meta.table
                            if related_model._meta.table else
                            related_model.__name__.lower())

                        m2m_object.through = "{}_{}".format(
                            model._meta.table, related_model_table_name)

                    m2m_relation = fields.ManyToManyField(
                        "{}.{}".format(app_name, model_name),
                        m2m_object.through,
                        forward_key=m2m_object.backward_key,
                        backward_key=m2m_object.forward_key,
                        related_name=field,
                        type=model,
                    )
                    m2m_relation._generated = True
                    model._meta.filters.update(
                        get_m2m_filters(field, m2m_object))
                    related_model._meta.add_field(backward_relation_name,
                                                  m2m_relation)