Opened 3 years ago

Closed 3 years ago

Last modified 2 years ago

#30631 closed New feature (wontfix)

Prefixing Q Objects.

Reported by: Robert Schindler Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: prefix q objects
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: yes
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Robert Schindler)

I'm currently spending a lot of time on development of a project using Django and worked out something that I think could be of use for all Django users.

I added a new .prefix(prefix) method to the Q object, allowing to shift pre-built q objects to a related field. I think this can change the way people build managers completely, because instead of methods returning filtered querysets, one can just return Q objects, which can then be used from related models without repeating the filtering logic.

This is the simple implementation.

class Q(django.db.models.Q):
    """
    A custom Q implementation that allows prefixing existing Q objects with some
    related field name dynamically.
    """

    def prefix(self, prefix):
        """Recursively copies the Q object, prefixing all lookup keys.

        The prefix and the existing filter key are delimited by the lookup separator __.
        Use this feature to delegate existing query constraints to a related field.
        """
        return type(self)(
            *(
                child.prefix(prefix)
                if isinstance(child, Q)
                else (prefix + LOOKUP_SEP + child[0], child[1])
                for child in self.children
            ),
            _connector=self.connector,
            _negated=self.negated,
        )

What do you think, is it worth creating a PR for this functionality? I haven't written the docs yet, but could write something if you like the addition.

Best regards
Robert

Change History (4)

comment:1 Changed 3 years ago by Robert Schindler

Description: modified (diff)
Needs documentation: set
Needs tests: set

comment:2 Changed 3 years ago by Mariusz Felisiak

Resolution: wontfix
Status: newclosed
Summary: Prefixing Q ObjectsPrefixing Q Objects.
Version: 2.2master

Thanks for this proposition. It is interesting idea but I don't see many use cases and to be honest it would be confusing to me to use, e.g.:

Q(Q(field__startswith='x') | Q(other_field__startswith='y')).prefix('related_field') & Q(base_field__gte=78)

instead of

Q(Q(related_field__field__startswith='x') | Q(related_field__other_field__startswith='y')) & Q(base_field__gte=78)

Please write to the DevelopersMailingList if you want other opinions, we can re-open this ticket if we reach a consensus on the mailing list.

comment:3 Changed 3 years ago by Robert Schindler

Ok, I posted to the mailing list, but I think you've misunderstood the use case I proposed. Let's see how it goes.

comment:4 Changed 2 years ago by Valentijn Scholten

Note: See TracTickets for help on using tickets.
Back to Top