最近、サブクエリ機能が導入されたため、Django を最先端のバージョン 1.11rc1 に更新しました。
さて、これが私のユース ケースだとしましょう。次のモデルがあります-ユーザー、グループ、およびアクセス許可。したがって、グループ化できるユーザー (管理者グループなど) とアクセス許可があります。これは、いくつかのことを実行できるユーザーのリストです (たとえば、新しいユーザーを作成できるユーザー A、ユーザー B、および管理者がいます)。私が今やりたいことは、すべてのアクセス許可を効率的に表示することです。つまり、アクセス許可に関するすべての情報を返し、各アクセス許可のユーザー数を計算する QuerySet を作成したいと考えています。これを回避する最初の明白な方法は、get_user_count
ManyToMany リレーションシップからすべてのユーザーを返す Permission モデルのメソッドですが、それには Permission ごとに少なくとも 1 つの追加クエリが必要になります。使いたいところですSubquery
。
それで、物事を明確にするために-これはmodels.pyです:
class User(models.Model):
name = models.CharField(max_length=20)
class Group(models.Model):
users = models.ManyToManyField(User)
class Permission(models.Model):
users = models.ManyToManyField(User)
groups = models.ManyToManyField(Group)
そして、内部に多数のユーザーを含むすべてのアクセス許可を返すクエリセットを作成したいと考えています。例として、自分のグループに属するユーザーのみを含めたいとします。つまり、次のようになります。
groups = Group.objects.filter(permission=OuterRef('pk'))
users = User.objects.filter(group__in=groups)
queryset = Permission.objects.annotate(
user_no=Subquery(users.annotate(c=Count('*')).values('c'))
)
ここでの問題はOuterRef
、「サブクエリのフィルターのフィルター」で使用されているように my を解決できないことです。
This queryset contains a reference to an outer query and may only be used in a subquery.
ただし、別のサブクエリを使用してグループを取得すると、次のようになります。
groups = Group.objects.filter(permission=OuterRef(OuterRef('pk')))
users = User.objects.filter(group__in=Subquery(groups))
queryset = Permission.objects.annotate(
user_no=Subquery(users.annotate(c=Count('*')).values('c'))
)
最初の行でエラーが発生します。
int() argument must be a string, a bytes-like object or a number, not 'OuterRef'
残りの行は重要ではなく、エラーには影響しません。奇妙なことに、まったく同じ構文がドキュメントに表示されます: https://docs.djangoproject.com/en/dev/ref/models/expressions/#django.db.models.OuterRef
問題は、私が間違っていることは何ですか? または、他の方法で(効率的ではありますが)私が望むものを達成する方法は?