2đź‘Ť
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 …
14đź‘Ť
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.
- How to Hash Django user password in Django Rest Framework?
- Casting from base Model instance to derived proxy Model in Django?
- Django admin many-to-many intermediary models using through= and filter_horizontal
- Can I get expiration time of specified key in django cache?
0đź‘Ť
Here is a nice Python automapper that is possible to extend for any framework models:
- Django 1.9 drop foreign key in migration
- How to embed matplotlib graph in Django webpage?
- Django: How to save original filename in FileField?
- Related name for recursive many to many relationship not working
0đź‘Ť
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/ahanc**k1/5e5e0c665c3e696f1e8085f7b38bd123
- How to use Pagination in a Non-Generic View/Viewset?
- Error running Django in Intellij / Pycharm
- Django docker – could not translate host name "db" to address: nodename nor servname provided, or not known