Django: 如何清理用户列表

1 投票
2 回答
1159 浏览
提问于 2025-04-16 02:55

这是我出错的代码:

dashboard = Dashboard.objects.get(slug=slug)
users = User.objects.all() # list of users

for editor in dashboard.dashboardeditor_set.iterator:
    users.remove(editor.user)

错误信息:

‘instancemethod’对象不可迭代

来自models.py文件:

class DashboardEditor(models.Model):
    dashboard = models.ForeignKey(Dashboard)
    user = models.ForeignKey(User)

有没有人能帮我想办法从所有用户的列表中去掉编辑者?

谢谢!:)

2 个回答

0

可以结合使用 values_list()exclude() 来在一个查询中获取结果(里面有一个嵌套的 SELECT):

dash = Dashboard.objects.get(slug=slug)
User.objects.exclude(id__in=dash.dashboardeditor_set.values_list('user', flat=True))

这会生成以下的 SQL 语句:

SELECT "auth_user"."id",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."password",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."is_superuser",
       "auth_user"."last_login",
       "auth_user"."date_joined"
FROM "auth_user"
WHERE NOT ("auth_user"."id" IN
             (SELECT U0."user_id"
              FROM "dashboard_dashboardeditor" U0
              WHERE U0."dashboard_id" = 1)) LIMIT 21  [0.68ms]

使用 iterator 的话,大约会触发 N+2 次查询,其中 N 是给定 DashboardDashboardEditor 的数量:

In [24]: users = list(User.objects.all())
SELECT "auth_user"."id",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."password",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."is_superuser",
       "auth_user"."last_login",
       "auth_user"."date_joined"
FROM "auth_user"  [0.40ms]


In [25]: for editor in dash.dashboardeditor_set.iterator():
   ....:     users.remove(editor.user)
   ....: 
SELECT "dashboard_dashboardeditor"."id",
       "dashboard_dashboardeditor"."user_id",
       "dashboard_dashboardeditor"."dashboard_id"
FROM "dashboard_dashboardeditor"
WHERE "dashboard_dashboardeditor"."dashboard_id" = 1  [0.15ms]

SELECT "auth_user"."id",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."password",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."is_superuser",
       "auth_user"."last_login",
       "auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."id" = 2  [0.25ms]

SELECT "auth_user"."id",
       "auth_user"."username",
       "auth_user"."first_name",
       "auth_user"."last_name",
       "auth_user"."email",
       "auth_user"."password",
       "auth_user"."is_staff",
       "auth_user"."is_active",
       "auth_user"."is_superuser",
       "auth_user"."last_login",
       "auth_user"."date_joined"
FROM "auth_user"
WHERE "auth_user"."id" = 3  [0.24ms]

在这个例子中,有两个 DashboardEditor,所以 ORM 运行了 4 次查询来获取非编辑用户的结果列表。

2

我猜从错误信息来看,你可能缺少了括号:

 for editor in dashboard.dashboardeditor_set.iterator():

这是因为错误信息似乎暗示了iterator是一个实例方法,所以你需要调用它才能得到真正的迭代器。

撰写回答