Skip to content

Commit ff592e7

Browse files
committed
Use typehint to construct a dataclass if possible.
1 parent 1954125 commit ff592e7

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

django_unicorn/views.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22
import logging
3+
from dataclasses import is_dataclass
34
from functools import wraps
45
from typing import Any, Dict, List, Union, get_type_hints
56

@@ -158,7 +159,11 @@ def _set_property_from_data(
158159
# Usually the value will be a string (because it is coming from JSON)
159160
# and basic types can be constructed by passing in a string,
160161
# i.e. int("1") or float("1.1")
161-
value = type_hints[name](value)
162+
163+
if is_dataclass(type_hints[name]):
164+
value = type_hints[name](**value)
165+
else:
166+
value = type_hints[name](value)
162167

163168
if hasattr(component_or_field, "_set_property"):
164169
# Can assume that `component_or_field` is a component

tests/views/message/test_type_hints.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from dataclasses import dataclass
12
from decimal import Decimal
23

34
import orjson
@@ -6,12 +7,18 @@
67
from tests.views.message.utils import post_and_get_response
78

89

10+
@dataclass
11+
class ExampleDataclass:
12+
hello: str = "world"
13+
14+
915
class FakeObjectsComponent(UnicornView):
1016
template_name = "templates/test_component.html"
1117

1218
decimal_example: Decimal = Decimal(1.1)
1319
float_example: float = 1.2
1420
int_example: int = 3
21+
dataclass_example: ExampleDataclass = None
1522

1623
def assert_int(self):
1724
assert self.int_example == 4
@@ -22,6 +29,10 @@ def assert_float(self):
2229
def assert_decimal(self):
2330
assert self.decimal_example == Decimal(1.5)
2431

32+
def assert_dataclass(self):
33+
assert self.dataclass_example == ExampleDataclass(hello="world")
34+
assert self.dataclass_example.hello == "world"
35+
2536

2637
FAKE_OBJECTS_COMPONENT_URL = (
2738
"/message/tests.views.message.test_type_hints.FakeObjectsComponent"
@@ -71,3 +82,18 @@ def test_message_decimal(client):
7182
"error"
7283
) # UnicornViewError/AssertionError returns a a JsonResponse with "error" key
7384
assert not body["errors"]
85+
86+
87+
def test_message_dataclass(client):
88+
data = {"dataclass_example": {"hello": "world"}}
89+
action_queue = [{"payload": {"name": "assert_dataclass"}, "type": "callMethod",}]
90+
response = post_and_get_response(
91+
client, url=FAKE_OBJECTS_COMPONENT_URL, data=data, action_queue=action_queue,
92+
)
93+
94+
body = orjson.loads(response.content)
95+
96+
assert not body.get(
97+
"error"
98+
) # UnicornViewError/AssertionError returns a a JsonResponse with "error" key
99+
assert not body["errors"]

0 commit comments

Comments
 (0)