Django anota en varios campos relacionados con el mismo modelo.

Tengo dos modelos:

class Account(models.Model): ... class Transaction(models.Model): .... account = models.ForeignKey(Account) source_account = models.ForeignKey(Account, null=True) 

Necesito mostrar el número de transacciones para cada una de las cuentas de un usuario. La annotate de Django parecía la herramienta adecuada para esta tarea. Yo si:

 queryset = models.Account.objects.filter(user=self.request.user) queryset.annotate(transactions_count=Count('transaction')) 

Esto da el número correcto para transacciones con el campo de account establecido en la cuenta predicada, pero deja de lado las transacciones donde source_account se establece en la cuenta predicada.

Usando el shell de Django puedo hacer algo como:

 accounts_count = user_transactions.filter(Q(account=account)|Q(source_account=account)).count() 

Esto da la respuesta correcta. ¿Hay algo que estoy haciendo mal? ¿Puede alguien apuntarme en la dirección correcta? Cualquier asistencia es muy apreciada.

Yo establecería related_name a sus campos ForeignKey . Entonces es un poco más fácil trabajar con ellos. Así, por ejemplo, en tus modelos vamos a configurar:

 class Transaction(models.Model): ... account = models.ForeignKey(Account, related_name='transactions') source_account = models.ForeignKey(Account, null=True, related_name='source_transactions') 

entonces puede hacer algo como:

  queryset = models.Account.objects.filter(user=self.request.user).annotate(transactions_count=(Count('transactions')+Count('source_transactions')) 

Funcionaría sin el nombre también, es más fácil de leer y más fácil. El punto principal es agregar las dos Count como un campo en la annotate .

El mejor enfoque para este tipo de problemas es imaginarlos en SQL en bruto y luego intentar imitarlo en Django ORM. (en el sql sin formato, también simplemente agregaría dos columnas como SELECT (a.col + a.col2) AS count

El problema es que su transacción tiene que forgeinKeys to Account. Yo sugeriría intentar algo como esto

 class Transaction(models.Model): .... account = models.ForeignKey(Account, related_name="transaction_account") source_account = models.ForeignKey(Account, null=True, related_name="transaction_source_account") 

Luego en su consulta:

 queryset.annotate(transactions_count=((Count('transaction_account') + Count('transaction_source_account'))