Opened 15 years ago
Last modified 13 years ago
#13844 closed
ValueError: by adding custom aggregate function TRIM — at Initial Version
| Reported by: | Owned by: | nobody | |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.2 |
| Severity: | Normal | Keywords: | |
| Cc: | philipe.rp@… | 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
My intension is joining tables with two different formated columns,
by using django's double underscore magic to resolve the querysets.
The values in table B are preceded by leading zeros.
table A --> id = "10"
table B --> id = "000010"
select distinct b.id from a, b where where a.id = TRIM(leading '0' FROM b.id);
The resulting code should look like this
qs_a=A.objects.all().values('id')
qs_b=B.objects.annotate(id_trim=Trim('id', position='leading', char='0')).filter(id_trim__in=qs_a)
I use the following code to implement the extra functionality.
try:
import psycopg2
except ImportError, e:
import psycopg
else:
psycopg = psycopg2._psycopg
class Trim(django.db.models.Aggregate):
name = 'Trim_pg'
django.db.models.Trim=Trim
class Trim_pg(django.db.models.sql.aggregates.Aggregate):
'''
position = [leading, trailing, both]
char = <character to remove>
'''
sql_function = 'TRIM'
sql_template = '''%(function)s(%(position)s %(char)s FROM %(field)s)'''
def __init__(self, col, distinct=False, **extra):
assert extra.has_key('position'), u'no position'
assert extra['position'] in ('leading', 'trailing', 'both'), 'position no in [leading, trailing, both]'
assert extra.has_key('char'), u'no char'
assert len(extra['char']) == 1, 'only one character'
extra['char']=str(psycopg2._psycopg.QuotedString(extra['char'])) #Quoting
super(Trim_pg, self).__init__(col, distinct=distinct, **extra)
django.db.models.sql.aggregates.Trim_pg=Trim_pg
The problem is, that "convert_values" makes for a "CharField"
a cast to float. My solution is to return the value for CharFields
without the cast.
Index: db/backends/__init__.py
===================================================================
--- db/backends/__init__.py (Revision 12595)
+++ db/backends/__init__.py (Arbeitskopie)
@@ -438,6 +438,8 @@
return int(value)
elif internal_type in ('DateField', 'DateTimeField', 'TimeField'):
return value
+ elif internal_type in ('CharField'):
+ return value
# No field, or the field isn't known to be a decimal or integer
# Default to a float
return float(value)