Opened 6 days ago

Closed 5 days ago

Last modified 5 days ago

#36291 closed Bug (worksforme)

ManyToManyField empty when setting related_name and related_query_name to "+"

Reported by: Hayder Mustafa Owned by:
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords:
Cc: Hayder Mustafa Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no
Pull Requests:How to create a pull request

Description

I’ve encountered an issue in my Django project where using the following configuration in a ManyToManyField causes the field to return an empty queryset—even though the underlying join table contains records. Notably, this bug appears to be intermittent; sometimes the field behaves as expected, while other times it consistently returns an empty queryset.

move_lines = models.ManyToManyField(
    "accounting.AccountMoveLine",
    verbose_name="Move Lines",
    related_name="+",
    related_query_name="+",
    blank=True,
)

Steps to Reproduce:

Define a model with a ManyToManyField that includes related_name="+" and related_query_name="+" (to disable reverse relations).

Create and save related records so that there are entries in the join table.

Query the field using instance.move_lines.all().

Observe that the queryset is empty despite the related records existing. Note that the bug does not occur consistently—there are occasions where the field returns the expected records.

Expected Behavior:
The field should return all associated records when queried, regardless of the reverse relation being disabled.

Actual Behavior:
When related_name and related_query_name are set to "+", instance.move_lines.all() sometimes returns an empty queryset even though related records exist. Removing these attributes (thus allowing Django to generate default reverse names) consistently resolves the issue.

Additional Context:
This appears to be an issue where disabling the reverse relationship by setting the related names to "+" intermittently interferes with the ORM’s ability to construct the proper join, resulting in an empty result set on the forward lookup. Has anyone else experienced this behavior, or is there a known workaround or fix for this issue?

Thanks in advance for any help or insights!

Change History (1)

comment:1 by Sarah Boyce, 5 days ago

Resolution: worksforme
Status: newclosed

I cannot replicate, can you try to write a regression test?

This was what I have tested:

  • TabularUnified tests/m2m_regress/models.py

    a b class RegressionModelSplit(BadModelWithSplit):  
    9393class Post(models.Model):
    9494    primary_lines = models.ManyToManyField(Line, related_name="+")
    9595    secondary_lines = models.ManyToManyField(Line, related_name="+")
     96
     97
     98class Test(models.Model):
     99    lines = models.ManyToManyField(Line, related_name="+", related_query_name="+")
  • TabularUnified tests/m2m_regress/tests.py

    diff --git a/tests/m2m_regress/tests.py b/tests/m2m_regress/tests.py
    index d3f352ffd9..075c140867 100644
    a b from .models import (  
    1111    SelfReferChildSibling,
    1212    Tag,
    1313    TagCollection,
     14    Test,
    1415    Worksheet,
    1516)
    1617
    class M2MRegressionTests(TestCase):  
    141142        post.secondary_lines.add(bar)
    142143        self.assertSequenceEqual(post.primary_lines.all(), [foo])
    143144        self.assertSequenceEqual(post.secondary_lines.all(), [bar])
     145
     146    def test_related_name_and_related_query_name_plus(self):
     147        instance = Test.objects.create()
     148        foo = Line.objects.create(name="foo")
     149        bar = Line.objects.create(name="bar")
     150        instance.lines.add(foo)
     151        instance.lines.add(bar)
     152        self.assertSequenceEqual(instance.lines.all(), [foo, bar])
     153        instance.refresh_from_db()
     154        self.assertSequenceEqual(instance.lines.all(), [foo, bar])
Last edited 5 days ago by Sarah Boyce (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top