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'))