diff --git a/CHANGELOG.md b/CHANGELOG.md index ce7c1daa..62a202fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,9 @@ Using the following categories, list your changes in this order: ## [Unreleased] -- Nothing (yet) +### Fixed + +- `use_query` will now utilize `field.related_name` when postprocessing many-to-one relationships ## [2.2.1] - 2022-01-09 diff --git a/pyproject.toml b/pyproject.toml index 6bf3a9fc..a8a2fb0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,6 +10,7 @@ ensure_newline_before_comments = "True" include_trailing_comma = "True" line_length = 88 lines_after_imports = 2 +extend_skip_glob = ["*/migrations/*"] [tool.mypy] ignore_missing_imports = true diff --git a/src/django_idom/utils.py b/src/django_idom/utils.py index 9c76a9f9..52a4eed0 100644 --- a/src/django_idom/utils.py +++ b/src/django_idom/utils.py @@ -232,7 +232,7 @@ def django_query_postprocessor( getattr(data, field.name) if many_to_one and type(field) == ManyToOneRel: - prefetch_fields.append(f"{field.name}_set") + prefetch_fields.append(field.related_name or f"{field.name}_set") elif many_to_many and isinstance(field, ManyToManyField): prefetch_fields.append(field.name) diff --git a/tests/test_app/components.py b/tests/test_app/components.py index 29c3da30..37ae1cda 100644 --- a/tests/test_app/components.py +++ b/tests/test_app/components.py @@ -199,7 +199,7 @@ def relational_query(): mtm = relational_parent.data.many_to_many.all() oto = relational_parent.data.one_to_one - mto = relational_parent.data.foriegnchild_set.all() + mto = relational_parent.data.many_to_one.all() fk = foriegn_child.data.parent return html.div( diff --git a/tests/test_app/migrations/0003_alter_foriegnchild_parent_and_more.py b/tests/test_app/migrations/0003_alter_foriegnchild_parent_and_more.py new file mode 100644 index 00000000..7861029a --- /dev/null +++ b/tests/test_app/migrations/0003_alter_foriegnchild_parent_and_more.py @@ -0,0 +1,33 @@ +# Generated by Django 4.1.5 on 2023-01-13 23:23 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("test_app", "0002_relationalchild_relationalparent_foriegnchild"), + ] + + operations = [ + migrations.AlterField( + model_name="foriegnchild", + name="parent", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="parent", + to="test_app.relationalparent", + ), + ), + migrations.AlterField( + model_name="relationalparent", + name="one_to_one", + field=models.OneToOneField( + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="one_to_one", + to="test_app.relationalchild", + ), + ), + ] diff --git a/tests/test_app/migrations/0004_alter_foriegnchild_parent.py b/tests/test_app/migrations/0004_alter_foriegnchild_parent.py new file mode 100644 index 00000000..52e06cc8 --- /dev/null +++ b/tests/test_app/migrations/0004_alter_foriegnchild_parent.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.5 on 2023-01-13 23:28 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("test_app", "0003_alter_foriegnchild_parent_and_more"), + ] + + operations = [ + migrations.AlterField( + model_name="foriegnchild", + name="parent", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="foriegn_child", + to="test_app.relationalparent", + ), + ), + ] diff --git a/tests/test_app/migrations/0005_alter_foriegnchild_parent.py b/tests/test_app/migrations/0005_alter_foriegnchild_parent.py new file mode 100644 index 00000000..5a3a3ca0 --- /dev/null +++ b/tests/test_app/migrations/0005_alter_foriegnchild_parent.py @@ -0,0 +1,23 @@ +# Generated by Django 4.1.5 on 2023-01-13 23:38 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("test_app", "0004_alter_foriegnchild_parent"), + ] + + operations = [ + migrations.AlterField( + model_name="foriegnchild", + name="parent", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="many_to_one", + to="test_app.relationalparent", + ), + ), + ] diff --git a/tests/test_app/models.py b/tests/test_app/models.py index e001c06f..ba62938b 100644 --- a/tests/test_app/models.py +++ b/tests/test_app/models.py @@ -20,4 +20,4 @@ class RelationalParent(models.Model): class ForiegnChild(models.Model): text = models.CharField(max_length=1000) # type: ignore - parent = models.ForeignKey(RelationalParent, on_delete=models.CASCADE) # type: ignore + parent = models.ForeignKey(RelationalParent, related_name="many_to_one", on_delete=models.CASCADE) # type: ignore diff --git a/tests/test_app/tests/test_components.py b/tests/test_app/tests/test_components.py index 5c435f22..e5a77827 100644 --- a/tests/test_app/tests/test_components.py +++ b/tests/test_app/tests/test_components.py @@ -16,7 +16,7 @@ def setUpClass(cls): asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy()) # FIXME: This is required otherwise the tests will throw a `SynchronousOnlyOperation` - # error when deleting the test datatabase. Potentially a Django bug. + # error when discarding the test datatabase. Potentially a `ChannelsLiveServerTestCase` bug. os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true" super().setUpClass()