【问题标题】:How to count the amount of objects in a django joined table?如何计算 django 连接表中的对象数量?
【发布时间】:2014-02-26 01:41:48
【问题描述】:

我的问题很简单:我有 Users 拥有 AssetsAssets 属于 Users 如果您愿意,但我无法做到检索每个 User 拥有的 Assets 的数量(计数)。我知道这对你们大多数人来说可能听起来很傻,但我是 python/django 的新手(来自 PHP/MySQL),我不知道这里的工作原理。我不想接触原始 SQL - 如果没有其他方法,这将是我的最后选择。

(*) 我已经从代码中删除了所有不相关的原始数据

用户

class Users(models.Model):
    firstname = models.CharField(max_length=100)
    lastname = models.CharField(max_length=100)

资产

class Assets(models.Model):
    serial = models.CharField(unique=True, max_length=100)
    user = models.ForeignKey('Users', blank=True, null=True)

    # this is what I am playing with to retrieve the number of assets each user owns
    @classmethod
        def user_assets(self):
            return Assets.objects.filter(user=user).count()

views.py

class UserList(ListView):
    model = Users
    def get_context_data(self, **kwargs):
        context = super(UserList, self).get_context_data(**kwargs)
        context['user_assets'] = self.model.user_assets()
        return context

模板

{% for user in object_list %}
     <tr>
         <td>{{ user.id }}</td>
         <td>
             {{ user_assets }}
         </td>
     </tr>
{% endfor %}

我怎样才能得到那个号码?我已阅读有关聚合、注释和过滤器的信息,但无法真正理解。

编辑:

我正在寻找一个简单的解决方案,通过使用基于类的视图并且易于扩展(我以后可能想添加其他模型)

【问题讨论】:

  • 您需要使用 sql 连接,如果您不想乱用原始 sql,您可以尝试 django 的 select_related() 然后 count(),但您需要外键才能工作。
  • 我有一个从资产到用户的外键。许多资产属于一个用户,但两个用户不能拥有相同的资产。
  • 是的,你是对的,没有注意到,尝试选择相关也许它会做。
  • 它没有。我试过“return cls.objects.select_related(None).count()”和“return cls.objects.select_related('assets').count()”,我总是得到全部资产。
  • 开头的 cls 是什么?您需要类似:Assets.objects.prefetch_related('Users').filter(user=user).count()

标签: python mysql sql django


【解决方案1】:

在您的 UserList 中使用模型,而不是使用此查询集:

from django.db.models import Count

class UserList(ListView):
    queryset = Users.objects.annotate(num_assets=Count('assets'))

并像这样定义您的 user 字段:

user = models.ForeignKey('Users', blank=True, null=True, related_name='assets')

然后从模板:

{{ user.num_assets }}

另外请记住,使用单数模型名称是一种很好的做法,以避免与反向关系名称混淆..

【讨论】:

  • 我得到“'ForeignRelatedObjectsDescriptor'对象没有属性'count'”
  • 'ForeignRelatedObjectsDescriptor' 对象没有属性 'all'
  • 我觉得我必须导入一些库
  • @RobDel 哦,我想问题是,您访问的是类而不是视图中的对象 (self.model)。
  • @RobDel 好的,我做了最终版,试试看,在这种情况下你不需要自定义方法。
【解决方案2】:

您需要使用select_related()count() 并将用户实例作为参数传递给类方法,如下所示:

@classmethod
def user_assets(cls,user):
    return Assets.objects.select_related('Users').filter(user=user).count()

然后像这样使用它:

user = Users.objects.all()[0] # some user object (this assumes you have at least one user)
Assets.user_assets(user) 

这应该可以正常工作,你可以在 shell 中尝试一下。

在您的上下文中,这将像这样使用:

user = self.model.all()[0] # or get or filter just get some particular user
context['user_assets'] = Assets.user_assets(user)

编辑:添加链接和 Users.object.all() 而不是 Users.object.get(),还添加了适合您特定用例的示例。

【讨论】:

  • 我应该把你的代码的第二段放在哪里?在views.py中?
  • 第一部分也给了我一个错误“user_assets() missing 1 required positional argument: 'user'”
  • 是的,在视图中,您确定要将用户对象传递给资产吗?这个 pk=1 只是一个例子,你可能没有 id 为 1 的用户,关键是将用户实例作为参数传递给过滤器,以便 django 将选择范围缩小到一个用户实例。
  • 类型对象“用户”没有属性“全部”。有什么想法吗?
【解决方案3】:

你在做奇怪的事情。改用 django 给你的相关管理器。我会将视图编写为基于函数的视图:

views.py

def users_list(request):
    object_list = Users.objects.all()
    render(request, 'mytemplate.html', { 'object_list': object_list })

您可以通过 RelatedManager 直接在模板中获取计数:

mytemplate.html

{% for user in object_list %}
 <tr>
     <td>{{ user.id }}</td>
     <td>
         {{ user.assets_set.count }}
     </td>
 </tr>
{% endfor %}

您也可以使用计数进行注释。但是在游泳之前学会漂浮:)

顺便说一句,您应该将模型称为“用户”和“资产”,而不是用户和资产。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-24
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    相关资源
    最近更新 更多