2

I have the following models:

class Person(...):
    name = CharField(...)

class Address(...):
    person = ForeignKey(Person)
    address = CharField(...)

I need to select all persons that have exactly two addresses.

So if my Address table looks like this:

----------------------------
| id | person_id | address |
----------------------------
| 1  | 1         | xyz     |
| 2  | 1         | xyz     |
| 3  | 2         | xyz     |
| 4  | 3         | xyz     |
| 5  | 3         | xyz     |
| 6  | 4         | xyz     |
| 7  | 5         | xyz     |
| 8  | 5         | xyz     |
| 9  | 5         | xyz     |
----------------------------

The resulting queryset should be

<QuerySet [<Person: 1>, <Person: 3>]>

I tried a lot, but just don't seem to get it right. I would be glad for a quick fix.

iBug
  • 35,554
  • 7
  • 89
  • 134
Daniel
  • 3,092
  • 3
  • 32
  • 49
  • Please do not vandalize your posts. By posting on Stack Overflow, you've granted a non-revocable right for SO to distribute that content under the [CC BY-SA 3.0 license](https://creativecommons.org/licenses/by-sa/3.0/). By SO policy, any vandalism will be reverted. – iBug Feb 06 '18 at 13:50

1 Answers1

1

Try to use annotate:

from django.db.models import Count
Person.objects.annotate(address_count=Count('address')).filter(
address_count=2)
neverwalkaloner
  • 46,181
  • 7
  • 92
  • 100
  • @Daniel check updates. Also do you use related_name? It should be related_name value in this case. – neverwalkaloner Feb 06 '18 at 11:07
  • @neverwalkaloner where do you see that `Person` model has an `address` field ? – albar Feb 06 '18 at 13:16
  • 1
    @albar I dont see. From django docs related_query_name: It defaults to the value of related_name or default_related_name if set, otherwise it defaults to the name of the model. So Default is model_name, address in our case. – neverwalkaloner Feb 06 '18 at 13:21
  • 1
    It's best to define your own related_name (improves code readability), I would update the `Address` model to have `person = ForeignKey(Person, related_name='addresses')` then you can use the person instance field `my_person.addresses` to get their addresses. – Stefan Collier Feb 06 '18 at 13:32