Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#28446 closed Cleanup/optimization (invalid)

QuerySet.extra is required for using SQL functions in SELECT clause

Reported by: Chuck Horowitz Owned by: nobody
Component: Database layer (models, ORM) Version: 1.11
Severity: Normal Keywords: QuerySet.extra
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

In this case, I have a table that is indexed and queried based on long integer IP addresses. My QuerySet will ultimately be passed along to a serializer expecting an IPAddressField compatible item however, which must be a valid IPv4 string. So I would like SQL that looks like:

SELECT INET_NTOA(iplong) AS ip, COUNT(*) AS count FROM ipTable  GROUP BY INET_NTOA(iplong) ORDER BY count DESC;

To do this with ORM and QuerySet.extra() looks like:

Model.extra(select={'ip': 'INET_NTOA(iplong)'}).values('ip').annotate(count=Count('*')).order_by('-count')

This is not a problem for my application, but I wanted to pass this along as requested in the documentation. Additionally, perhaps there is a better/more idomatic way of doing this (not requiring QuerySet.extra()) that you might be able to point me towards.

Thanks for making a great framework!

Best,
Chuck

Change History (2)

comment:1 by Simon Charette, 7 years ago

Resolution: invalid
Status: newclosed

Hello Chuck,

You should be able to use Func for this purpose.

from django.db import models
from django.db.models import Func, F

Model.objects.annotate(
   ip=Func(F('iplong'), function='INET_NTOA', output_field=models.CharField(max_length=15)),
).values('ip').annotate(count=Count('*')).order_by('-count')

You can even define your own Func subclass and use it instead.

class INetNTOA(Func):
   function = 'INET_NTOA'
   output_field = models.CharField(max_length=15)

Model.objects.annotate(
   ip=INetNTOA(F('iplong')),
).values('ip').annotate(count=Count('*')).order_by('-count')

comment:2 by Charles Horowitz, 7 years ago

Okay great! I will adjust my code to make use of Func and F come Monday. Thanks a million for the quick and helpful response! I love Django! Feel free to close this ticket

Thanks again all,
Best,
Chuck

Note: See TracTickets for help on using tickets.
Back to Top