【问题标题】:Field return count of another table另一个表的字段返回计数
【发布时间】:2019-12-11 03:35:57
【问题描述】:

我需要 read_booksfield(已购买),返回 Rating 对象计数。

应该根据Rating中每本书的同一个集合和同一个用户的过滤器返回对象个数。

我不知道该怎么做,因为RatingPurchased 没有直接依赖关系。

评级/models.py

class Rating(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
    book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False)
    rating = models.IntergerField(default=0)

book/models.py

class Books(models.Model):      
    collection = models.ForeignKey(Collection, on_delete=models.DO_NOTHING, blank=True, null=True)
    book = models.CharField(max_length=250, blank=True, null=True)

collection/models.py

class Collection(models.Model):
    title = models.CharField(max_length=50)
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)

purchased_collections/models.py

class Purchased(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
    collection = models.ForeignKey(Collection, on_delete=models.DO_NOTHING)
    date = models.DateTimeField(default=datetime.now) 
    read_books = models.IntegerField(default=0)

应用@ruddra 的回复后

第一个选项:

    def read_books(self):
        return Rating.objects.filter(user=self.user, book__collection=self.collection).count()

曾在models.py 工作。但我只想在用户登录时运行此功能。 所以我试着把它放在views.py中的def login (request):, 但是,它不是基于class,我不能使用(self)。总是返回错误name 'self' is not defined.

所以,我尝试了第二个@ruddra 的建议:

purchases = Purchased.objects.annotate(read_books=Count('collection__books__rating', filter=Q(collection__books__rating__user=F('user'))))
for item in purchases:
    print(item.read_books)

views.py

from django.shortcuts import render, redirect, get_object_or_404
from django.contrib import messages
from .login import login_user

from purchased.models import Purchased
from rating.models import Rating
from collection.models import Collection
from book.models import Books

from django.db.models import F, Count, Q

def login(request):
    if not request.user.is_authenticated:
        if request.method == 'POST':
            login_status = login_user(request)
            if login_status != 1:
                messages.error(request, 'Invalid')
                return redirect('login')
            else:
                messages.success(request, 'You are now logged in')

                purchases = Purchased.objects.annotate(read_books=Count('collection__books__rating', filter=Q(collection__books__rating__user=F('user'))))
                for item in purchases:
                   print(item.read_books)


                return redirect('home')

        else:
            return render(request, 'users/login.html')
    else:
        messages.error(request, 'You are already logged in')
        return redirect('index')

但曾经返回错误:NameError: name 'collection__books__rating__user' is not defined.

问题是能够通过自己的collection 过滤每个ratings 对象。在models.py 中使用 (self) 可以完美运行,但如果没有 (self),我将无法使其正常运行。

还有什么其他建议可以让这个计数只在用户登录时运行?

【问题讨论】:

  • book = models.ForeignKey(Statement, on_delete=models.CASCADE, null=False) 准确还是应该是book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False)
  • 是的,你是对的。对不起。我已经编辑过了。

标签: python django postgresql django-models


【解决方案1】:

假设您的意思是 book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False) in Rating 模型:

可以使用属性方法返回计数:

class Purchased(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
    collection = models.ForeignKey(Collection, on_delete=models.DO_NOTHING)
    date = models.DateTimeField(default=datetime.now) 

    @property
    def read_books(self):
        return Rating.objects.filter(user=self.user, book__collection=self.collection).count()

或者更好,如果您使用annotation(这将减少数据库命中,您可以使用它进行查询):

from django.db.models import Count, F, Q

purchases = Purchased.objects.annotate(read_books=Count('collection__books__rating', filter=Q(collection__books__rating__user=F('user'))))

for item in purchases:
    print(item.read_books)

【讨论】:

  • NameError: name 'collection__statement__progress__user' 未定义。怎么了?
  • 发生了同样的错误。我编辑了问题以试图澄清情况。
【解决方案2】:

如cmets中所述,如果您使用Book作为外键相关模型,那么您可以通过以下方式找出计数:

class Purchased(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
    collection = models.ForeignKey(Collection, on_delete=models.DO_NOTHING)
    date = models.DateTimeField(default=datetime.now) 
    read_books = models.IntegerField(default=0)

    def save(self):
        self.read_books = Rating.objects.filter(user=self.user, book__in=self.collection.books_set).count()
        return super().save()

【讨论】:

  • 我只是想在用户登录时运行这个功能。我试图将此函数与登录函数一起放在 view.py 中,但它不起作用并且没有返回任何错误。所以,它只适用于模型。用户登录时我该怎么做才能运行此功能?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-26
  • 2020-09-24
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多