CatsLoveJazz
CatsLoveJazz

Reputation: 869

Filtering Django models by user & object

I'm learning Django with a dummy example but having difficulty in understanding how to correctly filter my Django models by an authorised user in my views.

In my view I want to list the transactions associated with a users portfolio. The code below runs but when trying to access the result of 't' I get the error:

'ValueError: The QuerySet value for an exact lookup must be limited to one result using slicing.'

Any help would be much appreciated, thanks.

if request.user.is_authenticated:
    # Get model data
    pf = Portfolio.objects.filter(user=request.user)
    t = Transaction.objects.filter(pf=pf)

My model is as below:

from django.db import models
from django.contrib.auth.models import User


class Portfolio(models.Model):

    # Portfolio has one user associated with it
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    name = models.CharField(max_length=100, default='-')

    def __str__(self):
        return self.name


class Transaction(models.Model):
    # Transaction has one equity associated with it
    equity = models.ForeignKey('Equity', on_delete=models.CASCADE, null=True)

    # Transaction has one portfolio associated with it
    pf = models.ForeignKey('Portfolio', on_delete=models.CASCADE)

    BUY = 'BUY'
    SELL = 'SELL'
    BUY_OR_SELL = (
        (BUY, 'BUY'),
        (SELL, 'SELL'),
    )
    action = models.CharField(choices=BUY_OR_SELL, default=BUY, max_length=5)
    num = models.FloatField(default=1)
    price = models.FloatField(default=0)
    date = models.DateField('date')
    fee = models.FloatField(default=0)

    def __str__(self):
        return f'{self.equity}, {self.num}x{self.price}, {self.date:%d %b %Y}'


class Equity(models.Model):
    class Meta:
        verbose_name_plural = "Equities"

    CUR_EUR = 'EUR'
    CUR_GBP = 'GBP'
    CUR_USD = 'USD'
    CURRENCY_CHOICES = (
        (CUR_EUR, 'EUR'),
        (CUR_GBP, 'GBP'),
        (CUR_USD, 'USD'),
    )
    symbol = models.CharField(max_length=20, default='-')
    exchange = models.CharField(max_length=100, default='-')
    currency = models.CharField(max_length=15, choices=CURRENCY_CHOICES, default=CUR_USD)

    def __str__(self):
        return self.symbol

Many thanks!

Upvotes: 1

Views: 930

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476584

pf is here a collection of Portfolio objects, so you can query it with the __in lookup [Django-doc]:

Transaction.objects.filter(pf__in=pf)

Or if you are not interested in the Porfolio objects itself, you can make a query like:

Transaction.objects.filter(pf__user=request.user)

The query below will result in a query like:

SELECT transaction.*
FROM transaction
JOIN portfolio ON transaction.pf_id = portfolio.id
WHERE porfolio.user_id = 123

(with 123 the id of the request.user)

Upvotes: 1

Related Questions