Opened 2 years ago

Last modified 2 years ago

#33838 closed Bug

Querying issue with ForeignKeys where db_constraint=False — at Version 1

Reported by: Alex Bailey Owned by: nobody
Component: Database layer (models, ORM) Version: 4.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Alex Bailey)

models.py

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=25)

class Book(models.Model):
    foo = models.ForeignKey(Person, db_constraint=False, on_delete=models.DO_NOTHING, related_name='foo')
    bar = models.ForeignKey(Person, db_constraint=False, on_delete=models.DO_NOTHING, related_name='bar')

setup

from .models import Book, Person

alex = Person.objects.create(name='Alex')

Book.objects.create(foo=alex, bar=alex)
Book.objects.create(foo=alex, bar_id=999)
Book.objects.create(foo_id=999, bar=alex)

shell

>>> from django.db.models import Q

#Correct: Returns both books where foo__name == 'Alex'
>>> Book.objects.filter(foo__name='Alex') 
<QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>

#Correct: Returns both books where bar__name == 'Alex'
>>> Book.objects.filter(bar__name='Alex')
<QuerySet [<Book: Book object (1)>, <Book: Book object (3)>]>

#Only returns one book, expected to return all 3. 
>>> Book.objects.filter(Q(foo__name='Alex') | Q(bar__name='Alex'))
<QuerySet [<Book: Book object (1)>]>

I am working with an existing DB where it is possible for a Person to no longer exist, hence the lack of db_constraint in the ForeignKey.

Books can refer to non-existent Persons but it still seems like expected behavior would be for the queryset OR to return all 3 books. I believe this is coming from the Django ORM doing an INNER JOIN. The 3rd query should be a simple union of the first 2 queries.

All 3 books fit into the expected query of books WHERE foo__name = 'Alex' OR bar__name = 'Alex' but the Django behavior does not reflect this.

Change History (1)

comment:1 by Alex Bailey, 2 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top