首页 > 解决方案 > 按用户和对象过滤 Django 模型

问题描述

我正在通过一个虚拟示例学习 Django,但很难理解如何在我的视图中由授权用户正确过滤我的 Django 模型。

在我看来,我想列出与用户投资组合相关的交易。下面的代码运行,但是当试图访问 't' 的结果时,我得到了错误:

“ValueError:精确查找的 QuerySet 值必须使用切片限制为一个结果。”

任何帮助将不胜感激,谢谢。

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

我的模型如下:

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

非常感谢!

标签: djangodjango-models

解决方案


pf这里是Portfolio对象的集合,因此您可以使用__in查找 [Django-doc]来查询它:

Transaction.objects.filter(pf__in=pf)

或者,如果您对对象本身不感兴趣Porfolio,您可以进行如下查询:

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

下面的查询将产生如下查询:

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

(与123的)idrequest.user


推荐阅读