首页 > 解决方案 > 另一个表的字段返回计数

问题描述

我需要该read_books字段(在已购买),返回Rating对象计数。

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

我不知道该怎么做,因为Rating并且Purchased不直接依赖。

评级/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)

书/模型.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)

集合/models.py

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

购买的_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. 但是我想只有在用户登录时才运行这个功能。所以我试图把它放在def login (request):views.py中,但是,它不是基于a的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)

视图.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.

问题是能够ratings按自己的方式过滤每个对象collection。在其中使用 (self)models.py可以完美地工作,但没有 (self) 我无法使其工作。

仅在用户登录时才运行此计数的任何其他建议?

标签: pythondjangopostgresqldjango-models

解决方案


假设您的意思book = models.ForeignKey(Book, on_delete=models.CASCADE, null=False)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)

推荐阅读