#1530 closed enhancement (fixed)
[patch] making distinct=True work with get_count
| Reported by: | anonymous | Owned by: | Adrian Holovaty | 
|---|---|---|---|
| Component: | Core (Other) | Version: | 0.91 | 
| Severity: | normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | yes | Needs documentation: | no | 
| Needs tests: | no | Patch needs improvement: | no | 
| Easy pickings: | no | UI/UX: | no | 
Description
Currently get_count() ignores a distinct=True argument. This patch fixes that.
Unfortunately, company firewall issues don't allow me to use svn, so I don't have an svn-diff patch. Sorry about pasting code into the ticket body. For the same reason, I'm using the 0.91 tarball, not the svn version, though I believe the patch is the same for both (I don't think the method in question has changed). In magic-removal, the same idea should work, but it looks like the syntax would be slightly different.
Here's the changed method in django/core/meta/__init__.py (commented out lines are the originals, with the changed version below them):
def function_get_count(opts, **kwargs):
    kwargs['order_by'] = []
    kwargs['offset'] = None
    kwargs['limit'] = None
    kwargs['select_related'] = False
#    _, sql, params = function_get_sql_clause(opts, **kwargs)
    select, sql, params = function_get_sql_clause(opts, **kwargs)
    cursor = db.db.cursor()
#    cursor.execute("SELECT COUNT(*)" + sql, params)
    cursor.execute("SELECT COUNT(" + (kwargs.get('distinct') and "DISTINCT %s" % select[0] or "*")  + ")" + sql, params)
    return cursor.fetchone()[0]
      Change History (4)
comment:1 by , 20 years ago
comment:2 by , 20 years ago
I was looking over this patch and had a "wait a minute" thought...
What's the use-case for this? In which case would get_count(distinct=True) return a different result than get_count()?
The distinct option uses SELECT DISTINCT across every row, and each row is guaranteed to be distinct because it requires a primary key.
comment:3 by , 20 years ago
Yeah, see, this is why I asked on django-dev first ;). Its possible I'm missing something, but here's my use case:
class Category(meta.Model):
    name = meta.CharField(maxlength=100)
class Business(meta.Model):
    name = meta.CharField(maxlength=100)
    category = meta.ManyToManyField(Category)
>>> c1 = categories.Category(name='pizzarias') >>> c2 = categories.Category(name='pizza restaurants') >>> cpk = businesses.Business(name="Bob's pizza") >>> cpk.set_category([c1.id, c2.id]) >>> businesses.get_count(category__name__icontains='pizza') 2 >>> businesses.get_list(category__name__icontains='pizza') ["Bob's pizza", "Bob's pizza"] >>> businesses.get_count(category__name__icontains='pizza', distinct=True) # with this patch 1 >>> businesses.get_list(category__name__icontains='pizza', distinct=True) ["Bob's pizza"]
(sorry about any errors introduced by simplifying this)
Basically it looks like the generated SQL is causing a hit for each category that matches the criteria. Now that I think about it though, it may just be a coincidence that this patch is working for my case, because its distinguishing on the business.id, which just happens to be what select[0] gives in this case? I'm not enough of an SQL guru for this, I just know this works for my particular use.
comment:4 by , 19 years ago
| Resolution: | → fixed | 
|---|---|
| Status: | new → closed | 
Oops, sorry, didn't mean to submit as anonymous.