Skip to content

Commit e85d58c

Browse files
committed
Support model binding to a foreign key.
1 parent 2bc92bb commit e85d58c

File tree

7 files changed

+55
-11
lines changed

7 files changed

+55
-11
lines changed

django_unicorn/views/action_parsers/utils.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,23 @@ class TestView(UnicornView):
6161
if hasattr(component, updating_function_name):
6262
getattr(component, updating_function_name)(property_value)
6363

64-
setattr(component_or_field, property_name_part, property_value)
64+
is_relation_field = False
65+
66+
# Set the id property for ForeignKeys
67+
if hasattr(component_or_field, "_meta"):
68+
for field in component_or_field._meta.fields:
69+
if field.name == property_name_part:
70+
if field.is_relation:
71+
setattr(
72+
component_or_field,
73+
field.attname,
74+
property_value,
75+
)
76+
is_relation_field = True
77+
break
78+
79+
if not is_relation_field:
80+
setattr(component_or_field, property_name_part, property_value)
6581

6682
if hasattr(component, updated_function_name):
6783
getattr(component, updated_function_name)(property_value)
@@ -77,19 +93,12 @@ class TestView(UnicornView):
7793
else:
7894
component_or_field = component_or_field[property_name_part]
7995
data_or_dict = data_or_dict.get(property_name_part, {})
80-
elif isinstance(component_or_field, list):
96+
elif isinstance(component_or_field, list) or isinstance(
97+
component_or_field, QuerySet
98+
):
8199
# TODO: Check for iterable instad of list? `from collections.abc import Iterable`
82100
property_name_part = int(property_name_part)
83101

84-
if idx == len(property_name_parts) - 1:
85-
component_or_field[property_name_part] = property_value
86-
data_or_dict[property_name_part] = property_value
87-
else:
88-
component_or_field = component_or_field[property_name_part]
89-
data_or_dict = data_or_dict[property_name_part]
90-
elif isinstance(component_or_field, QuerySet):
91-
property_name_part = int(property_name_part)
92-
93102
if idx == len(property_name_parts) - 1:
94103
component_or_field[property_name_part] = property_value
95104
data_or_dict[property_name_part] = property_value

example/unicorn/components/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@ def save(self, flavor_idx: int):
2424
def delete(self, flavor_to_delete: Flavor):
2525
flavor_to_delete.delete()
2626
self.refresh_flavors()
27+
28+
def available_flavors(self):
29+
return Flavor.objects.all()
30+
31+
class Meta:
32+
javascript_exclude = ("available_flavors",)

example/unicorn/templates/unicorn/models.html

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ <h4>{{ flavor.pk }}</h4>
4444
{{ flavor.decimal_value }}
4545
<br />
4646

47+
<label>Parent</label>
48+
<select unicorn:model="flavors.{{ forloop.counter0 }}.parent">
49+
<option value="">n/a</option>
50+
{% for available_flavor in available_flavors %}
51+
<option value="{{ available_flavor.pk }}">{{ available_flavor.name }}</option>
52+
{% endfor %}
53+
</select>
54+
{{ flavor.parent.name }}
55+
<br />
56+
4757
<button unicorn:click="save({{ forloop.counter0 }})">save(flavor_idx)</button>
4858
<button unicorn:click="delete({{ flavor.pk }})">delete(flavor.pk)</button>
4959
</div>

tests/management/__init__.py

Whitespace-only changes.

tests/management/commands/__init__.py

Whitespace-only changes.

tests/management/commands/startunicorn/__init__.py

Whitespace-only changes.

tests/views/test_unicorn_set_property_value.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,22 @@ def test_set_property_value_array():
5959
)
6060

6161
assert component.flavors[0].name == "test 1"
62+
63+
64+
@pytest.mark.django_db
65+
def test_set_property_value_foreign_key():
66+
flavor = Flavor(name="initial 1")
67+
flavor.save()
68+
parent = Flavor(name="initial 2")
69+
parent.save()
70+
component = FakeComponent(component_name="test", component_id="12345678")
71+
72+
set_property_value(
73+
component,
74+
"flavors.0.parent",
75+
parent.pk,
76+
{"flavors": [{"name": flavor.name, "parent": None},]},
77+
)
78+
79+
assert component.flavors[0].parent_id == parent.pk
80+
assert component.flavors[0].parent.pk == parent.pk

0 commit comments

Comments
 (0)