Opened 14 years ago
Last modified 12 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)