There are three models A, B, C:

Class A: some_field = models.CharF... Class B: a = models.ForeignKey('A') с = models.ForeignKey('С') Class C some_field = models.CharF... 

How can Django orm get the number of A objects belonging to C?

For example:
There are objects: A1, A2.
Object: C1.
And connections: B1 (A1, C1), B2 (A1, C1), B3 (A2, C1).

In this example, the number of objects A belonging to C will be 2.

I tried this:

 queryset = A.objects.all() queryset.values('b__c').annotate(num_results=Count('b__c')) 

As a result, I get that the object C1 belongs to 3 objects. Thus, I consider the number of connections that does not suit me.

  • a = models.ForeignKey ('A') - is the field required? If the quantity is needed, the first table is not needed at all where A - Igor
  • Yes, the field is required. I did not understand the second part where you wrote that table A is not needed. Under the condition of the problem it is written: get the number of objects A belonging to C. - Max
  • Wrote the answer, in table B are the links. A link uniquely indicates an ID in table A, so it is not necessary to request data from tables other than B. But you need to count the number of unique ones. - Igor

2 answers 2

The final code, explanations will be lower.

 filter(c__some_field='значение').values('a').distinct().count() 

As far as I understand the model, there are 3 physical tables, 'A', 'B', 'C'.

In table 'B' there are all the necessary connections, we only need to remove duplicates, table A as such is not required.

Make a selection of all records from table B

 filter(c__some_field='значение') 

We extend this query further, but leave one value to remove duplicates.

 .values('a') 

and remove doubles

 distinct() 

Now we consider

 .count() 

It depends on the task, the same can be done through python, got a value, removed set duplicates, found out the length of the array.

    In this particular case:

     a = A.objects.create() # создаём экземпляр А c = C.objects.create() # создаём экземпляр С a.c__set.add(c) # через менеджер связанных моделей добавляем "с" к "а" a.c__set.filter(c).count() # смотрим количество всех записей связанных с "с" 

    You can still like this:

     a = A.objects.create() # создаём экземпляр А c = C.objects.create() # создаём экземпляр С b = B.objects.create(a=a, c=c) # создаём экземпляр B B.objects.filter(a=a, c=c).count() # смотрим количество записей 

    In general, you can add the many_to_many field to the model:

     Class A: some_field = models.CharF... cs = models.ManyToManyField("C") 
    • Thanks for the answer, but you do not need to change the condition, as this is a simplified example, in fact, class B, in addition to the connections themselves, stores a lot of information about the connection. B.objects.filter (a = a, c = c) .count () returns the number of links, which is similar to what I described in the question - it does not fit. - Max
    • Then the question is not clear. What you need to get? - Mr Fix
    • a.c__set.add(c) you probably meant b__set ? - Max
    • I'll try to paraphrase. You need to get the number of objects A used in the links to object C. Look again at the example in question. In the example, links B1 and B2 are the same. they mean that object A1 is associated with object C1. Link B3 means that the object A2 is associated with C1. As a result, two objects A1 and A2 are associated with object C1. - Max
    • If the instances themselves are needed, not the quantity, then it suffices to remove count () - Mr. Fix