Ticket #11402: exists.2.diff

File exists.2.diff, 5.4 KB (added by Alex, 6 years ago)

Fixed docs and made has_results() work more like get_count(). This doesn't need tests because it is trivially shown to work because forms and save() continue to work (which are both tested extensively).

  • django/contrib/admin/validation.py

    diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py
    index 05e5c6d..595b951 100644
    a b def validate(cls, model): 
    150150
    151151def validate_inline(cls, parent, parent_model):
    152152   
     153    fk = _get_foreign_key(parent_model, cls.model, fk_name=cls.fk_name, can_fail=True)
     154   
    153155    # model is already verified to exist and be a Model
    154156    if cls.fk_name: # default value is None
    155157        f = get_field(cls, cls.model, cls.model._meta, 'fk_name', cls.fk_name)
    156158        if not isinstance(f, models.ForeignKey):
    157159            raise ImproperlyConfigured("'%s.fk_name is not an instance of "
    158160                    "models.ForeignKey." % cls.__name__)
    159 
    160     fk = _get_foreign_key(parent_model, cls.model, fk_name=cls.fk_name, can_fail=True)
    161 
    162161    # extra = 3
    163162    # max_num = 0
    164163    for attr in ('extra', 'max_num'):
  • django/db/models/base.py

    diff --git a/django/db/models/base.py b/django/db/models/base.py
    index a5c9986..30b12da 100644
    a b class Model(object): 
    467467            if pk_set:
    468468                # Determine whether a record with the primary key already exists.
    469469                if (force_update or (not force_insert and
    470                         manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by())):
     470                        manager.filter(pk=pk_val).exists())):
    471471                    # It does already exist, so do an UPDATE.
    472472                    if force_update or non_pks:
    473473                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
  • django/db/models/manager.py

    diff --git a/django/db/models/manager.py b/django/db/models/manager.py
    index 52612d8..73d2bf5 100644
    a b class Manager(object): 
    172172
    173173    def only(self, *args, **kwargs):
    174174        return self.get_query_set().only(*args, **kwargs)
     175   
     176    def exists(self, *args, **kwargs):
     177        return self.get_query_ste().exists(*args, **kwargs)
    175178
    176179    def _insert(self, values, **kwargs):
    177180        return insert_query(self.model, values, **kwargs)
  • django/db/models/query.py

    diff --git a/django/db/models/query.py b/django/db/models/query.py
    index 46a86fc..02288c1 100644
    a b class QuerySet(object): 
    443443        self._result_cache = None
    444444        return query.execute_sql(None)
    445445    _update.alters_data = True
     446   
     447    def exists(self):
     448        if self._result_cache is None:
     449            return self.query.has_results()
     450        return bool(self._result_cache)
    446451
    447452    ##################################################
    448453    # PUBLIC METHODS THAT RETURN A QUERYSET SUBCLASS #
  • django/db/models/sql/query.py

    diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py
    index 23f99e4..ad0998b 100644
    a b class BaseQuery(object): 
    383383            number = min(number, self.high_mark - self.low_mark)
    384384
    385385        return number
     386   
     387    def has_results(self):
     388        """
     389        Returns whether or not there are any items in the result set this Query
     390        represents.  Does this in a super tricking way.  Basically the
     391        equivalent of QuerySet.extra(select={'a': 1}).values('a').order_by()
     392        to maximize efficiency.
     393        """
     394        c = self.clone()
     395        c.add_extra({'a': 1}, None, None, None, None, None)
     396        c.add_fields(())
     397        c.set_extra_mask(('a',))
     398        c.set_aggregate_mask(())
     399        c.clear_ordering()
     400        results = self.execute_sql()
     401        return bool(results)
     402
    386403
    387404    def as_sql(self, with_limits=True, with_col_aliases=False):
    388405        """
  • django/forms/models.py

    diff --git a/django/forms/models.py b/django/forms/models.py
    index cc43612..37fce68 100644
    a b class BaseModelForm(BaseForm): 
    319319            if self.instance.pk is not None:
    320320                qs = qs.exclude(pk=self.instance.pk)
    321321
    322             # This cute trick with extra/values is the most efficient way to
    323             # tell if a particular query returns any results.
    324             if qs.extra(select={'a': 1}).values('a').order_by():
     322            if qs.exists():
    325323                if len(unique_check) == 1:
    326324                    self._errors[unique_check[0]] = ErrorList([self.unique_error_message(unique_check)])
    327325                else:
    class BaseModelForm(BaseForm): 
    354352            if self.instance.pk is not None:
    355353                qs = qs.exclude(pk=self.instance.pk)
    356354
    357             # This cute trick with extra/values is the most efficient way to
    358             # tell if a particular query returns any results.
    359             if qs.extra(select={'a': 1}).values('a').order_by():
     355            if qs.exists():
    360356                self._errors[field] = ErrorList([
    361357                    self.date_error_message(lookup_type, field, unique_for)
    362358                ])
  • docs/ref/models/querysets.txt

    diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
    index efd7c54..26c76ca 100644
    a b Aggregation <topics-db-aggregation>`. 
    11141114
    11151115.. _field-lookups:
    11161116
     1117``exists()``
     1118~~~~~~~~~~~~
     1119
     1120Returns whether or not there are any items in the ``QuerySet``.  This will
     1121perform the query in the most efficient way possible.
     1122
    11171123Field lookups
    11181124-------------
    11191125
Back to Top