Opened 11 months ago

Last modified 11 months ago

#35050 closed Bug

Issue filtering on FilteredRelation with F object — at Version 1

Reported by: Mark Zorn Owned by: nobody
Component: Database layer (models, ORM) Version: 5.0
Severity: Release blocker Keywords: FilteredRelation
Cc: Francesco Panico, David Wobrock Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Mark Zorn)

I just started trying to upgrade an existing project from Django 4.2.8 to Django 5 and ran across the following issue.

I have two classes:

class DashboardSuggestion(BaseModel):

    active = models.BooleanField(default=True)
    title = models.CharField(max_length=50)
    body = models.CharField(max_length=80)
    max_dismissals = models.IntegerField(default=1)
    days_between_dismissals = models.IntegerField(null=True, blank=True)

    objects = DashboardSuggestionQuerySet.as_manager()

    class Meta:
        db_table = 'dashboard_suggestion'
class DashboardSuggestionDismiss(BaseModel):
    suggestion = models.ForeignKey('suggestions.DashboardSuggestion', on_delete=models.CASCADE, related_name='dismissals')
    user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, blank=True)
    company = models.ForeignKey('companies.Company', on_delete=models.SET_NULL, null=True, blank=True)
    count = models.IntegerField(default=1)

    class Meta:
        db_table = 'dashboard_suggestion_dismiss'
        unique_together = ['user', 'suggestion', 'company']

And the following QuerySet:

class DashboardSuggestionQuerySet(models.QuerySet):
    def for_dashboard(self, user, company):
        queryset = self.annotate(
            is_dismissed=FilteredRelation(
                'dismissals',
                condition=(
                        Q(dismissals__user=user)
                        & Q(dismissals__company=company)
                        &
                        (
                            Q(dismissals__count__gte=F('max_dismissals'))
                            | Q(dismissals__updated__gt=timezone.now() - timezone.timedelta(days=1) * F('days_between_dismissals'))
                        )
                )
            ),
        ).filter(
            Q(is_dismissed__isnull=True),
        )

When I attempt to call DashboardSuggestion.objects.for_dashboard(user, company) I receive the following error:

Cannot resolve keyword 'days_between_is_dismissed' into field. Choices are...

The string days_between_is_dismissed does not exist anywhere in my code. I do not see where it is being used or generated at all.

Trying to do a bit of debugging, somehow the F('days_between_dismissals') in the FilteredRelation condition is getting converted to F(days_between_is_dismissed) but I have not yet found the exact place that is happening.

This code was working as I expected in Django 4.2.

Please let me know if I can supply any additional information.k

Change History (1)

comment:1 by Mark Zorn, 11 months ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top