Django - 预取过滤器不适用于多对多模型
Django - Prefetch filter does not work on Many to Many model
我想要一个 Group 的端点来过滤每周和每年的 Credits 对象。 Group 与 'through' arg 与 Membership 具有多对多关系。用户的成员外键。将 ForeignKey 归功于用户。
我有以下型号:
class Group(models.Model):
name = models.CharField(max_length=128, unique=True)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="memberships",
through='Membership')
class Membership(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="membership",
on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
class Credits(models.Model):
credits = models.IntegerField()
year = models.IntegerField(default=date.today().isocalendar()[0])
week = models.IntegerField(default=date.today().isocalendar()[1])
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="credits",
on_delete=models.CASCADE)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
username = NameField(max_length=25, unique=True,
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
序列化程序:
class MembershipSerializer(serializers.ModelSerializer):
username = serializers.ReadOnlyField(source='user.username')
credits = CreditsSerializer(source='user.credits', many=True, required=False, allow_null=True)
class Meta:
model = Membership
fields = ('id', 'is_admin', 'user_id', 'username', 'credits')
read_only_fields = ('id',)
depth = 1
class GroupSerializer(serializers.ModelSerializer):
memberships = MembershipSerializer(source='membership_set', many=True)
class Meta:
model = Group
fields = ('id', 'name', 'memberships')
我的群组观点是:
class GroupSet(generics.ListAPIView):
lookup_field = 'name'
serializer_class = GroupSerializer
def get_queryset(self):
year = self.request.query_params.get('year', None)
week = self.request.query_params.get('week', None)
name = self.request.query_params.get('name', None)
if name and week and year is not None:
prefetchCredits = Prefetch('members__credits',
queryset=Credits.objects.filter(year=year, week=week), to_attr='credit_objs')
group = Group.objects.filter(name__iexact=name).prefetch_related(prefetchCredits)
return group
Credits 过滤器不起作用。我之前使用过此视图结构,其中 Prefetch 上的过滤器确实有效,但模型没有多对多关系。
我试图遍历 prefetchCredits 以过滤出正确的对象,但我得到一个错误:'Prefetch' object is not iterable
我不断得到下面的结构。年和周过滤器应仅显示一个演职员表对象。
[
{
"id": 3,
"name": "Group2",
"memberships": [
{
"id": 3,
"user_id": 2,
"username": "test1",
"credits": [
{
"credits": 800,
"year": 2020,
"week": 41
},
{
"credits": 1000,
"year": 2020,
"week": 40
},
{
"credits": 996,
"year": 2020,
"week": 39
}
],
模型'Group'和class'Credit'之间没有直接联系,所以无法直接预取学分。
首先您需要预取相关会员(Membership)并使用多级预取来包含该会员的积分。
可以在预取内部的查询集上使用预取来构建多级预取结构。
prefetchCredits = Prefetch('user__credits', queryset=Credits.objects.filter(year=year, week=week))
prefetchMembership = Prefetch(
'membership_set',
queryset=Membership.objects.prefetch_related(prefetchCredits)
)
group = Group.objects.filter(name__iexact=name).prefetch_related(prefetchMembership)
此外,Credits Prefetch 的名称更改为 'users__credits' 以匹配序列化程序的名称 'source'。
我想要一个 Group 的端点来过滤每周和每年的 Credits 对象。 Group 与 'through' arg 与 Membership 具有多对多关系。用户的成员外键。将 ForeignKey 归功于用户。
我有以下型号:
class Group(models.Model):
name = models.CharField(max_length=128, unique=True)
members = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name="memberships",
through='Membership')
class Membership(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="membership",
on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
class Credits(models.Model):
credits = models.IntegerField()
year = models.IntegerField(default=date.today().isocalendar()[0])
week = models.IntegerField(default=date.today().isocalendar()[1])
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="credits",
on_delete=models.CASCADE)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=255, unique=True)
username = NameField(max_length=25, unique=True,
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
序列化程序:
class MembershipSerializer(serializers.ModelSerializer):
username = serializers.ReadOnlyField(source='user.username')
credits = CreditsSerializer(source='user.credits', many=True, required=False, allow_null=True)
class Meta:
model = Membership
fields = ('id', 'is_admin', 'user_id', 'username', 'credits')
read_only_fields = ('id',)
depth = 1
class GroupSerializer(serializers.ModelSerializer):
memberships = MembershipSerializer(source='membership_set', many=True)
class Meta:
model = Group
fields = ('id', 'name', 'memberships')
我的群组观点是:
class GroupSet(generics.ListAPIView):
lookup_field = 'name'
serializer_class = GroupSerializer
def get_queryset(self):
year = self.request.query_params.get('year', None)
week = self.request.query_params.get('week', None)
name = self.request.query_params.get('name', None)
if name and week and year is not None:
prefetchCredits = Prefetch('members__credits',
queryset=Credits.objects.filter(year=year, week=week), to_attr='credit_objs')
group = Group.objects.filter(name__iexact=name).prefetch_related(prefetchCredits)
return group
Credits 过滤器不起作用。我之前使用过此视图结构,其中 Prefetch 上的过滤器确实有效,但模型没有多对多关系。
我试图遍历 prefetchCredits 以过滤出正确的对象,但我得到一个错误:'Prefetch' object is not iterable
我不断得到下面的结构。年和周过滤器应仅显示一个演职员表对象。
[
{
"id": 3,
"name": "Group2",
"memberships": [
{
"id": 3,
"user_id": 2,
"username": "test1",
"credits": [
{
"credits": 800,
"year": 2020,
"week": 41
},
{
"credits": 1000,
"year": 2020,
"week": 40
},
{
"credits": 996,
"year": 2020,
"week": 39
}
],
模型'Group'和class'Credit'之间没有直接联系,所以无法直接预取学分。
首先您需要预取相关会员(Membership)并使用多级预取来包含该会员的积分。
可以在预取内部的查询集上使用预取来构建多级预取结构。
prefetchCredits = Prefetch('user__credits', queryset=Credits.objects.filter(year=year, week=week))
prefetchMembership = Prefetch(
'membership_set',
queryset=Membership.objects.prefetch_related(prefetchCredits)
)
group = Group.objects.filter(name__iexact=name).prefetch_related(prefetchMembership)
此外,Credits Prefetch 的名称更改为 'users__credits' 以匹配序列化程序的名称 'source'。