Ticket #8784: patch.diff

File patch.diff, 3.3 KB (added by Johntron, 7 years ago)

Patch to add HAVING clauses to QuerySets

  • django/db/models/sql/query.py

     
    8484        self.extra_tables = ()
    8585        self.extra_where = ()
    8686        self.extra_params = ()
     87        self.extra_having = ()
    8788        self.extra_order_by = ()
    8889
    8990    def __str__(self):
     
    186187        obj.extra_tables = self.extra_tables
    187188        obj.extra_where = self.extra_where
    188189        obj.extra_params = self.extra_params
     190        obj.extra_having = self.extra_having
    189191        obj.extra_order_by = self.extra_order_by
    190192        if self.filter_is_sticky and self.used_aliases:
    191193            obj.used_aliases = self.used_aliases.copy()
     
    292294            grouping = self.get_grouping()
    293295            result.append('GROUP BY %s' % ', '.join(grouping))
    294296
     297        if self.extra_having:
     298            result.append('HAVING %s' % self.extra_having[0])
     299
    295300        if ordering:
    296301            result.append('ORDER BY %s' % ', '.join(ordering))
    297302
     
    388393            if self.extra_where and rhs.extra_where:
    389394                raise ValueError("When merging querysets using 'or', you "
    390395                        "cannot have extra(where=...) on both sides.")
     396            if self.extra_having and rhs.extra_having:
     397                raise ValueError("When merging querysets using 'or', you "
     398                        "cannot have extra(having=...) on both sides.")
    391399        self.extra_select.update(rhs.extra_select)
    392400        self.extra_tables += rhs.extra_tables
    393401        self.extra_where += rhs.extra_where
    394402        self.extra_params += rhs.extra_params
     403        self.extra_having += rhs.extra_having
    395404
    396405        # Ordering uses the 'rhs' ordering, unless it has none, in which case
    397406        # the current ordering is used.
     
    15671576        self.related_select_cols = []
    15681577        self.related_select_fields = []
    15691578
    1570     def add_extra(self, select, select_params, where, params, tables, order_by):
     1579    def add_extra(self, select, select_params, where, params, tables, order_by, having):
    15711580        """
    15721581        Adds data to the various extra_* attributes for user-created additions
    15731582        to the query.
     
    15981607            self.extra_params += tuple(params)
    15991608        if tables:
    16001609            self.extra_tables += tuple(tables)
     1610        if having:
     1611            self.extra_having += tuple(having) 
    16011612        if order_by:
    16021613            self.extra_order_by = order_by
    16031614
  • django/db/models/query.py

     
    567567        return obj
    568568
    569569    def extra(self, select=None, where=None, params=None, tables=None,
    570               order_by=None, select_params=None):
     570              order_by=None, select_params=None, having=None):
    571571        """
    572572        Adds extra SQL fragments to the query.
    573573        """
    574574        assert self.query.can_filter(), \
    575575                "Cannot change a query once a slice has been taken"
    576576        clone = self._clone()
    577         clone.query.add_extra(select, select_params, where, params, tables, order_by)
     577        clone.query.add_extra(select, select_params, where, params, tables, order_by, having)
    578578        return clone
    579579
    580580    def reverse(self):
Back to Top