Opened 8 months ago
Closed 8 months ago
#36239 closed Bug (fixed)
ManyToManyField check error with invalid "to" when passing through/through_fields
| Reported by: | Jordan Hyatt | Owned by: | JaeHyuckSa |
|---|---|---|---|
| Component: | Core (System checks) | Version: | 5.1 |
| Severity: | Normal | Keywords: | check |
| Cc: | Jordan Hyatt | Triage Stage: | Ready for checkin |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | yes | UI/UX: | no |
Description
Bug was discussed in the forums herehttps://forum.djangoproject.com/t/manytomanyfield-error-message-with-incorrect-to-argument/39394.
Basically, if an invalid "to" argument is passed to ManyToManyField while also passing the through/through_fields arguments the check framework crashes giving unhelpful error message/traceback.
Minimal reproduceable example:
class Foo(Model):
pass
class Bar(Model):
foos = ManyToManyField(
to = "Fo", # NOTE incorrect "to" argument
through = 'FooBar',
through_fields = ('bar', 'foo')
)
class FooBar(Model):
foo = ForeignKey('Foo', on_delete=CASCADE)
bar = ForeignKey('Bar', on_delete=CASCADE)
Traceback:
File "django/core/checks/registry.py", line 88, in run_checks
new_errors = check(app_configs=app_configs, databases=databases)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "django/core/checks/model_checks.py", line 36, in check_all_models
errors.extend(model.check(**kwargs))
^^^^^^^^^^^^^^^^^^^^^
File "django/db/models/base.py", line 1691, in check
*cls._check_fields(**kwargs),
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "django/db/models/base.py", line 1828, in _check_fields
errors.extend(field.check(from_model=cls, **kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "django/db/models/fields/related.py", line 1400, in check
*self._check_relationship_model(**kwargs),
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "django/db/models/fields/related.py", line 1676, in _check_relationship_model
related_model._meta.object_name,
^^^^^^^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute '_meta'
Proposed Patch:
diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py
index 6a9cb12a90..dd4c09a4e3 100644
--- a/django/db/models/fields/related.py
+++ b/django/db/models/fields/related.py
@@ -1707,13 +1707,18 @@ def _check_relationship_model(self, from_model=None, **kwargs):
and getattr(field.remote_field, "model", None)
== related_model
):
+ related_object_name = (
+ related_model
+ if isinstance(related_model, str)
+ else related_model._meta.object_name
+ )
errors.append(
checks.Error(
"'%s.%s' is not a foreign key to '%s'."
% (
through._meta.object_name,
field_name,
- related_model._meta.object_name,
+ related_object_name,
),
hint=hint,
obj=self,
Change History (17)
comment:1 by , 8 months ago
comment:2 by , 8 months ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:3 by , 8 months ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:4 by , 8 months ago
| Needs tests: | set |
|---|---|
| Patch needs improvement: | set |
comment:5 by , 8 months ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
comment:6 by , 8 months ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:7 by , 8 months ago
| Owner: | removed |
|---|---|
| Status: | assigned → new |
comment:8 by , 8 months ago
Hi Django Team,
I noticed that PR #19248 is currently open for this issue, but some unresolved test failures remain.
Is the current contributor still working on it, or would it be okay for me to assist in fixing the remaining issues?
Thanks!
comment:9 by , 8 months ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:10 by , 8 months ago
Hey Django Team,
I’d love to jump on ticket #36239 (ManyToManyField crash with invalid to). Can you assign it to @Amaan-ali03? I’ve dug into the issue and want to implement the fix.
Issue:
An invalid to (e.g., "Fo") with through/through_fields crashes with AttributeError: 'str' has no '_meta' because related_model isn’t handled properly.
Proposed Fix:
Update _check_relationship_model in django/db/models/fields/related.py with a type check:
related_object_name = (
related_model if isinstance(related_model, str) else related_model._meta.object_name
)
errors.append(
checks.Error(
f"'{through._meta.object_name}.{field_name}' is not a foreign key to '{related_object_name}'.",
obj=self,
)
)
comment:11 by , 8 months ago
| Needs tests: | unset |
|---|---|
| Patch needs improvement: | unset |
comment:12 by , 8 months ago
Fixes #36239: Prevents AttributeError: 'str' object has no attribute '_meta' in ManyToManyField when to is invalid with through/through_fields.
- Issue: The validation framework assumed
related_modelwas always resolved, causing a crash when it remained a string. - Fix: If
related_modelis a string, we handle it gracefully in_check_relationship_model. - Test: Added test in
tests/model_fields/tests.pyto confirm expected error messages (E300,E339). - Impact: Prevents crashes and ensures Django correctly raises validation errors instead.
follow-up: 14 comment:13 by , 8 months ago
We appreciate your interest Tanishq but there's no need to step in here.
JaeHyuckSa's PR is already passing the full suite with any failures and is only awaiting a final review.
comment:14 by , 8 months ago
Replying to Simon Charette:
We appreciate your interest Tanishq but there's no need to step in here.
JaeHyuckSa's PR is already passing the full suite with any failures and is only awaiting a final review.
okay, thanks for informing me, I will continue contributing in other issues, if that's fine?
comment:15 by , 8 months ago
sure, try to find tickets that don't already have any active owner and ready for review PRs.
comment:16 by , 8 months ago
| Triage Stage: | Accepted → Ready for checkin |
|---|
Hey Django Team,
I’d love to work on this issue!
Requesting to assign this ticket to @Amaan-ali03 to implement the proposed fix for the ManyToManyField error with an invalid "to" argument.
Proposed Approach:
Identify the Issue: The bug occurs when an invalid "to" argument is passed to ManyToManyField along with through and through_fields, causing an AttributeError due to improper handling of the related_model variable.
Proposed Solution: Update the _check_relationship_model method in django/db/models/fields/related.py to include a type check for related_model. Instead of directly accessing related_model._meta, the code should verify if related_model is a string and handle it accordingly to avoid the crash.