5๐
โ
As I said in my comment that you can simply copy the source code of Cast
class and save it in your projects and use it.
Turns out it wasnโt as simple as that. You will also need to change the Cast.as_sql
as it is in v1.10. And, no need to make a super
call to Func.as_sql
.
Just copy the following code and save it in your project. Iโve tested it and it works.
from django.db.models import Func, fields
class Cast(Func):
"""
Coerce an expression to a new field type.
"""
function = 'CAST'
template = '%(function)s(%(expressions)s AS %(db_type)s)'
mysql_types = {
fields.CharField: 'char',
fields.IntegerField: 'signed integer',
fields.FloatField: 'signed',
}
def __init__(self, expression, output_field):
super(Cast, self).__init__(expression, output_field=output_field)
def as_sql(self, compiler, connection, function=None, template=None, arg_joiner=None, **extra_context):
if 'db_type' not in extra_context:
extra_context['db_type'] = self._output_field.db_type(connection)
connection.ops.check_expression_support(self)
sql_parts = []
params = []
for arg in self.source_expressions:
arg_sql, arg_params = compiler.compile(arg)
sql_parts.append(arg_sql)
params.extend(arg_params)
data = self.extra.copy()
data.update(**extra_context)
# Use the first supplied value in this order: the parameter to this
# method, a value supplied in __init__()'s **extra (the value in
# `data`), or the value defined on the class.
if function is not None:
data['function'] = function
else:
data.setdefault('function', self.function)
template = template or data.get('template', self.template)
arg_joiner = arg_joiner or data.get('arg_joiner', self.arg_joiner)
data['expressions'] = data['field'] = arg_joiner.join(sql_parts)
return template % data, params
def as_mysql(self, compiler, connection):
extra_context = {}
output_field_class = type(self._output_field)
if output_field_class in self.mysql_types:
extra_context['db_type'] = self.mysql_types[output_field_class]
return self.as_sql(compiler, connection, **extra_context)
def as_postgresql(self, compiler, connection):
# CAST would be valid too, but the :: shortcut syntax is more readable.
return self.as_sql(compiler, connection, template='%(expressions)s::%(db_type)s')
๐คxyres
2๐
As you mentioned in question for django 1.10 you can use built-in Cast function. For older versions you can use Func() expression
from django.db.models import Count, Func, F, ExpressionWrapper, FloatField
tagged_user_posts = Query.objects.filter(Q(tags__id__in=tags_list)).
annotate(num_tags=Func(Count('tags'),
template='%(function)s(%(expressions)s AS %(type)s)',
function='Cast',
type='float')
).
annotate(post_scores=ExpressionWrapper(F('num_tags')+F('post_score'), output_field=FloatField())).
order_by('-post_scores')
๐คDima Kudosh
- [Django]-Inheritance model update to its parent model
- [Django]-Django annotate group by date return object
- [Django]-Django-lfs "No module named appconf"
- [Django]-Single django app to use multiple sqlite3 files for database
0๐
You could define Cast
as
def Cast(what, as_type):
if isinstance(as_type, Field):
as_type = as_type.db_type(connection)
return Func(
what,
template='%(function)s(%(expressions)s AS %(type)s)',
function='Cast',
type=as_type,
)
๐คMax Peterson
- [Django]-Which is the best python framework for developing Facebook application as on now
- [Django]-Django | twilio to send SMS
- [Django]-How to do math operations in django template?
- [Django]-Define component schema with drf-spectacular for django API
Source:stackexchange.com