I have a simple Google Calendar Events application. Profiles generate
calendar tokens with GSuite Oauth (not shown) that are used to make
CalendarEvents in my database (postgres:9.6). CalendarEvents queried via a
particular CalendarToken have the token's profile on the model. See
oversimplified example below:
{{{
class Profile(models.Model):
name = models.CharField(max_length=32)
class CalendarEvent(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
attendees = models.ManyToManyField(Profile, on_delete=models.CASCADE)
}}}
I'm trying to annotate whether a profile is "attending" the event, by
checking if the profile is in the attendees ManyToMany:
{{{
CalendarEvent.objects.annotate(
is_attending=Case(
When(
profile__in=F('attendees'),
then=Value(True)
),
default=Value(False),
output_field=models.BooleanField()
)
)
}}}
Generates an invalid syntax error (replacing db name with'' {APP}''):
{{{
ProgrammingError: syntax error at or near
""{APP}_calendarevent_attendees""
LINE 1: ...CASE WHEN ("{APP}_calendarevent"."profile_id" IN "{APP}_ca...
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/32414>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Old description:
New description:
Similar to https://code.djangoproject.com/ticket/32151
I have a simple Google Calendar Events application. Profiles generate
calendar tokens with GSuite Oauth (not shown) that are used to make
CalendarEvents in my database (postgres:9.6). CalendarEvents queried via a
particular CalendarToken have the token's profile on the model. See
oversimplified example below:
{{{
class Profile(models.Model):
name = models.CharField(max_length=32)
class CalendarEvent(models.Model):
profile = models.ForeignKey(Profile, on_delete=models.CASCADE)
attendees = models.ManyToManyField(Profile, blank=True,
related_name="attending_calendar_events")
}}}
I'm trying to annotate whether a profile is "attending" the event, by
checking if the profile is in the attendees ManyToMany:
{{{
CalendarEvent.objects.annotate(
is_attending=Case(
When(
profile__in=F('attendees'),
then=Value(True)
),
default=Value(False),
output_field=models.BooleanField()
)
)
}}}
Generates an invalid syntax error (replacing db name with'' {APP}''):
{{{
ProgrammingError: syntax error at or near
""{APP}_calendarevent_attendees""
LINE 1: ...CASE WHEN ("{APP}_calendarevent"."profile_id" IN "{APP}_ca...
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/32414#comment:1>
Comment (by Simon Charette):
Looks like you either want `attendees=F('profile')` or
`profile__in=CalendarEvent.attendees.through.objects.filter(calendarevent=OuterRef('pk'))`.
I guess we could raise a Python level error or adjust
`RelatedIn.get_prep_lookup` special case `F` referring to many-to-many as
well.
--
Ticket URL: <https://code.djangoproject.com/ticket/32414#comment:2>
Comment (by Douglas Franklin):
The latter worked perfectly. Really interesting. Thank you! I agree
though, seems like a practical use-case to have the special case when
`get_prep_lookup` `F` refers to a many-to-many.
The use of the through-table subquery is working for me, so it seems like
an easy enough workaround.
Replying to [comment:2 Simon Charette]:
> Looks like you either want `attendees=F('profile')` or
`profile__in=CalendarEvent.attendees.through.objects.filter(calendarevent=OuterRef('pk')).values('profile')`.
>
> I guess we could raise a Python level error or adjust
`RelatedIn.get_prep_lookup` special case `F` referring to many-to-many as
well.
--
Ticket URL: <https://code.djangoproject.com/ticket/32414#comment:3>
* status: new => closed
* resolution: => duplicate
Comment:
Duplicate of #31135. Please feel-free to add a comment to the original
ticket.
--
Ticket URL: <https://code.djangoproject.com/ticket/32414#comment:4>