Annotated queryset + Prefetch object

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Annotated queryset + Prefetch object

Jose Kilo
Hi all,

I'm trying to use an annotated queryset inside a Prefetch object. For some reason I'm not getting the expected result.
This is a simplified version of my models and query.


class User(models.Model):

    following
= models.ManyToManyField('User', related_name='followers', through='Follow')


class Follow(models.Model):

    following
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_followed')
    followed
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_following')


def test():

   
User.objects.all().delete()

    user_1
= User.objects.create()
    user_2
= User.objects.create()

   
Follow.objects.create(following=user_1, followed=user_2)

    queryset
= (
       
User.objects.all()
       
.prefetch_related(
           
Prefetch(
               
'followers', to_attr='prefetched_annotated_followers',
                queryset
=(User.objects.all().annotate(
                    followers_count
=Count('followers', distinct=True),
               
))
           
),
           
Prefetch(
               
'followers', to_attr='prefetched_followers',
                queryset
=User.objects.all()
           
),
       
)
   
)

    user
= queryset.last()
   
print(list(user.followers.all()))            # [<User: User object>]
   
print(user.prefetched_followers)             # [<User: User object>]
   
print(user.prefetched_annotated_followers)   # []

   
return queryset


Why the last result is empty ?

Just in case, I added 'prefetched_followers' to compare both results. If I remove it, 'prefetched_annotated_followers' still doesn't get anything.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/f81e26c5-38fa-4675-86b3-45e782175335%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Annotated queryset + Prefetch object

Simon Charette
Hello Jose,

I wouldn't be surprised if this was caused by a Django bug with prefetches doing
weird things when the same model is referenced through different relations[0].

Simon

[0] https://code.djangoproject.com/ticket/26318

Le samedi 4 mars 2017 13:36:20 UTC-5, Jose Kilo a écrit :
Hi all,

I'm trying to use an annotated queryset inside a Prefetch object. For some reason I'm not getting the expected result.
This is a simplified version of my models and query.


class User(models.Model):

    following
= models.ManyToManyField('User', related_name='followers', through='Follow')


class Follow(models.Model):

    following
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_followed')
    followed
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_following')


def test():

   
User.objects.all().delete()

    user_1
= User.objects.create()
    user_2
= User.objects.create()

   
Follow.objects.create(following=user_1, followed=user_2)

    queryset
= (
       
User.objects.all()
       
.prefetch_related(
           
Prefetch(
               
'followers', to_attr='prefetched_annotated_followers',
                queryset
=(User.objects.all().annotate(
                    followers_count
=Count('followers', distinct=True),
               
))
           
),
           
Prefetch(
               
'followers', to_attr='prefetched_followers',
                queryset
=User.objects.all()
           
),
       
)
   
)

    user
= queryset.last()
   
print(list(user.followers.all()))            # [<User: User object>]
   
print(user.prefetched_followers)             # [<User: User object>]
   
print(user.prefetched_annotated_followers)   # []

   
return queryset


Why the last result is empty ?

Just in case, I added 'prefetched_followers' to compare both results. If I remove it, 'prefetched_annotated_followers' still doesn't get anything.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/a79f26af-b4ef-4ba7-9c5a-353a900d891a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Annotated queryset + Prefetch object

Jose Kilo
Hello Simon,

That issue looks very similar indeed. I will keep an eye on that ticket.

Thanks for your reply.

Jose


El domingo, 9 de abril de 2017, 1:58:55 (UTC+1), Simon Charette escribió:
Hello Jose,

I wouldn't be surprised if this was caused by a Django bug with prefetches doing
weird things when the same model is referenced through different relations[0].

Simon

[0] <a href="https://code.djangoproject.com/ticket/26318" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fcode.djangoproject.com%2Fticket%2F26318\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE07PHJCX37vTWxHbp_sO1Y2Xk-DQ&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fcode.djangoproject.com%2Fticket%2F26318\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNE07PHJCX37vTWxHbp_sO1Y2Xk-DQ&#39;;return true;">https://code.djangoproject.com/ticket/26318

Le samedi 4 mars 2017 13:36:20 UTC-5, Jose Kilo a écrit :
Hi all,

I'm trying to use an annotated queryset inside a Prefetch object. For some reason I'm not getting the expected result.
This is a simplified version of my models and query.


class User(models.Model):

    following
= models.ManyToManyField('User', related_name='followers', through='Follow')


class Follow(models.Model):

    following
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_followed')
    followed
= models.ForeignKey(User, on_delete=models.CASCADE, related_name='_following')


def test():

   
User.objects.all().delete()

    user_1
= User.objects.create()
    user_2
= User.objects.create()

   
Follow.objects.create(following=user_1, followed=user_2)

    queryset
= (
       
User.objects.all()
       
.prefetch_related(
           
Prefetch(
               
'followers', to_attr='prefetched_annotated_followers',
                queryset
=(User.objects.all().annotate(
                    followers_count
=Count('followers', distinct=True),
               
))
           
),
           
Prefetch(
               
'followers', to_attr='prefetched_followers',
                queryset
=User.objects.all()
           
),
       
)
   
)

    user
= queryset.last()
   
print(list(user.followers.all()))            # [<User: User object>]
   
print(user.prefetched_followers)             # [<User: User object>]
   
print(user.prefetched_annotated_followers)   # []

   
return queryset


Why the last result is empty ?

Just in case, I added 'prefetched_followers' to compare both results. If I remove it, 'prefetched_annotated_followers' still doesn't get anything.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/b1f8a006-2de0-45da-b51f-6775da2d0de5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Loading...