Is there a python implementation to .net automapper?

Question:

Automapper is a object-object mapper where we can use to project domain model to view model in asp.net mvc.

http://automapper.codeplex.com/

Is there equivalent implementation in Python for use in Django(Template)/Pylons ?
Or is there necessity for this in Python world?

Asked By: stoto

||

Answers:

This generally isn’t necessary in Python. We have some pretty complex domain models and we’re able to use them in our views easily, without noticing any performance issues, and we serve millions of page views a month.

Also remember that “view” in Django == “controller” in MVC, and “template” in Django is “view” in MVC. Hence MTV rather than MVC. Something that tripped me up initially 🙂

If there’s some specific issue you’re running into, post that as a question too …

Answered By: godswearhats

Yes, There is.

ObjectMapper is a class for automatic object mapping. It helps you to create objects between project layers (data layer, service layer, view) in a simple, transparent way.

https://pypi.python.org/pypi/object-mapper

Answered By: Frederico Cabral

Here is a nice Python automapper that is possible to extend for any framework models:

https://pypi.org/project/py-automapper/

Answered By: andnik

I ended up rolling my own basic version of automapper modelled on the .net version.

from typing import Protocol, TypeVar, Callable

from dataclasses import is_dataclass, fields
from dataclasses import MISSING

S = TypeVar("S")
T = TypeVar("T")


class IProfile(Protocol):

    mappings: dict[tuple[type[S], type[T]], dict[str, Callable[[S], object]]]

    def create_map(self,
                source_type: type[S],
                target_type: type[T],
                **mappings: Callable[[S], object]) -> None:
        ...


class IMapper(Protocol):

    def map(self, data: object, data_type: type[T]) -> T:
        ...


class Profile:

    mappings: dict[tuple[type[S], type[T]], dict[str, Callable[[S], object]]]

    def __init__(self) -> None:

        self.mappings = {}

    def create_map(self,
                source_type: type[S],
                target_type: type[T],
                **mappings: Callable[[S], object]) -> None:

        self.mappings[(source_type, target_type)] = dict(mappings)


class Mapper:

    _mappings: dict[tuple[type[S], type[T]], dict[str, Callable[[S], object]]]

    def __init__(self, profiles: list[IProfile]) -> None:

        self._mappings = {}

        for profile in profiles:
            for key, value in profile.mappings.items():
                self._mappings[key] = value

    def map(self, data: object, data_type: type[T]) -> T:

        if not is_dataclass(data_type):
            raise TypeError("type must be a dataclass")

        mapping_key = (type(data), data_type,)

        data_fields = fields(data_type)
        data_params = {}

        mappings = self._mappings.get(mapping_key, {})

        for field in data_fields:

            field_name, field_type = field.name, field.type
            field_value = getattr(data, field_name, None)

            if is_dataclass(field_type):
                field_value = self.map(field_value, field_type)
            else:
                if field_name in mappings:
                    field_value = mappings[field_name](field_value)

                if not field_value and field.default is not MISSING:
                    field_value = field.default

            data_params[field_name] = field_value

        return data_type(**data_params)

I won’t claim it’s perfect but it works well enough for what I required.

https://gist.github.com/ahancock1/5e5e0c665c3e696f1e8085f7b38bd123

Answered By: Adam H
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.