#27982: Possible race condition related to queryset union
-------------------------------------+-------------------------------------
     Reporter:  gigelu               |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  1.11
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:                       |             Triage Stage:
                                     |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by gigelu:

Old description:

> I found a strange bug: the results from a paginator are affected randomly
> by setting breakpoints in the IDE.
>
> The bug appears '''only''' when I am using `union` on a queryset.
>
> I am using Django 1.11rc1 with DRF 3.6.2.
>
> The models:
> {{{
> class BaseNotification(models.Model):
>     user = models.ForeignKey(settings.AUTH_USER_MODEL,
> on_delete=models.CASCADE)
>     type = models.CharField(max_length=10, choices=TYPES,
> default=TYPE_SIMPLE, blank=True)
>     popup_type = models.CharField(max_length=10, choices=POPUP_TYPES,
> default=POPUP_DEFAULT)
>     title = models.CharField(max_length=200, blank=True)
>     message = models.TextField()
>     completed = models.BooleanField(blank=True, default=False)
>     date_completed = models.DateTimeField(null=True, blank=True,
> default=None)
>     date_created = models.DateTimeField(auto_now_add=True)
>
> class SimpleNotification(BaseNotification):
>
>     def save(self, *args, **kwargs):
>         self.type = self.TYPE_SIMPLE
>         super().save(*args, **kwargs)
>

> class DecisionNotification(BaseNotification):
>         ... (not relevant)
> }}}
>
> The view:
> {{{
> class NotificationView(ListAPIView):
>     permission_classes = [IsAuthenticated]
>     filter_backends = [OrderingFilter]
>     ordering_fields = ['completed', 'date_created', 'type']
>     ordering = ['-completed', '-date_created']
>     serializer_class = NotificationSerializer
>
>     def get_queryset(self):
>         qs1 =
> SimpleNotification.objects.filter(user=self.request.user).only(
>             'type', 'popup_type', 'completed', 'date_created')
>         qs2 =
> DecisionNotification.objects.filter(user=self.request.user).only(
>             'type', 'popup_type', 'completed', 'date_created')
>         qs = qs1.union(qs2)
>         return qs
> }}}
>
> The serializer:
> {{{
> class NotificationSerializer(serializers.ModelSerializer):
>     title = serializers.CharField(source='the_title')
>
>     class Meta:
>         model = SimpleNotification
>         fields = ['type', 'popup_type', 'title', 'url', 'completed',
> 'date_created']
> }}}
>
> The problem: I have 5 notifications in DB (3 simple, 2 decision), but it
> returns only the first one in normal usage, and sometimes all or
> sometimes one when I am using breakpoints.
>
> I've isolated the problem near this line of code:
> https://github.com/tomchristie/django-rest-
> framework/blob/master/rest_framework/pagination.py#L208. If I put a
> breakpoint inside the paginator's init
> (https://github.com/django/django/blob/master/django/core/paginator.py#L29)
> I get the correct result every time.
>
> http://i.imgur.com/9zoikMQ.png
> http://i.imgur.com/bsHgxig.png
>
> I've also attached a video showing the results while using different
> breakpoints.

New description:

 I found a strange bug: the results from a paginator are affected randomly
 by setting breakpoints in the IDE.

 The bug appears '''only''' when I am using `union` on a queryset.

 I am using Django 1.11rc1 with DRF 3.6.2.

 The models:
 {{{
 class BaseNotification(models.Model):
     user = models.ForeignKey(settings.AUTH_USER_MODEL,
 on_delete=models.CASCADE)
     type = models.CharField(max_length=10, choices=TYPES,
 default=TYPE_SIMPLE, blank=True)
     popup_type = models.CharField(max_length=10, choices=POPUP_TYPES,
 default=POPUP_DEFAULT)
     title = models.CharField(max_length=200, blank=True)
     message = models.TextField()
     completed = models.BooleanField(blank=True, default=False)
     date_completed = models.DateTimeField(null=True, blank=True,
 default=None)
     date_created = models.DateTimeField(auto_now_add=True)

 class SimpleNotification(BaseNotification):

     def save(self, *args, **kwargs):
         self.type = self.TYPE_SIMPLE
         super().save(*args, **kwargs)


 class DecisionNotification(BaseNotification):
         ... (not relevant)
 }}}

 The view:
 {{{
 class NotificationView(ListAPIView):
     permission_classes = [IsAuthenticated]
     filter_backends = [OrderingFilter]
     ordering_fields = ['completed', 'date_created', 'type']
     ordering = ['-completed', '-date_created']
     serializer_class = NotificationSerializer

     def get_queryset(self):
         qs1 =
 SimpleNotification.objects.filter(user=self.request.user).only(
             'type', 'popup_type', 'completed', 'date_created')
         qs2 =
 DecisionNotification.objects.filter(user=self.request.user).only(
             'type', 'popup_type', 'completed', 'date_created')
         qs = qs1.union(qs2)
         return qs
 }}}

 The serializer:
 {{{
 class NotificationSerializer(serializers.ModelSerializer):
     title = serializers.CharField(source='the_title')

     class Meta:
         model = SimpleNotification
         fields = ['type', 'popup_type', 'title', 'url', 'completed',
 'date_created']
 }}}

 The problem: I have 5 notifications in DB (3 simple, 2 decision), but it
 returns only the first one in normal usage, and sometimes all or sometimes
 one when I am using breakpoints.

 I've isolated the problem near this line of code:
 https://github.com/tomchristie/django-rest-
 framework/blob/master/rest_framework/pagination.py#L208. If I put a
 breakpoint inside the paginator's init
 (https://github.com/django/django/blob/master/django/core/paginator.py#L29)
 I get the correct result every time.

 http://i.imgur.com/9zoikMQ.png
 http://i.imgur.com/bsHgxig.png

--

--
Ticket URL: <https://code.djangoproject.com/ticket/27982#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/064.d9e34f4d5b1e5df123aa94f96c457bb6%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to