#16055: Filtering over generic relations with TextField/CharField object_id
breaks
in postgres
--------------------------------------+------------------------------------
Reporter: anonymous | Owner: nobody
Type: Bug | Status: new
Component: contrib.contenttypes | Version: 1.3
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Comment (by Nekmo):
I have made a hack for Django-guardian. In my case, this query is the one
that fails:
{{{
from customers.models import CustomerMemberObjectPermission
CustomerMemberObjectPermission.objects.filter(service_api__service__service_name='foo')
# Raise DatabaseError
}}}
My models:
{{{
class CustomerMemberObjectPermission(UserObjectPermission):
objects = CustomerMemberObjectPermissionManager()
class ServiceApi(Model):
customer_permissions = GenericRelation(CustomerMemberObjectPermission,
object_id_field='object_pk',
related_query_name='service_api')
}}}
This is the wrong sql:
{{{
SELECT "guardian_userobjectpermission"."id",
"guardian_userobjectpermission"."permission_id",
"guardian_userobjectpermission"."content_type_id",
"guardian_userobjectpermission"."object_pk",
"guardian_userobjectpermission"."user_id" FROM
"guardian_userobjectpermission" INNER JOIN "services_serviceapi" ON
("guardian_userobjectpermission"."object_pk" = "services_serviceapi"."id"
AND ("guardian_userobjectpermission"."content_type_id" = 22)) INNER JOIN
"services_service" ON ("services_serviceapi"."service_id" =
"services_service"."id") INNER JOIN "customers_customer" ON
("services_service"."customer_id" = "customers_customer"."id") WHERE
"customers_customer"."customer_code" = BCL
}}}
The error is in the inner join. Django-guardian uses a field of type
string for object_pk. But my id is a integer type:
{{{
"guardian_userobjectpermission"."object_pk" = "services_serviceapi"."id"
}}}
The solution is to use a cast:
{{{
CAST("guardian_userobjectpermission"."object_pk" AS integer) =
"services_serviceapi"."id"
}}}
Although I know it is not the best, my solution has been this hack thanks
to Simon Charette:
{{{
class CustomJoin(Join):
def as_sql(self, compiler, connection):
sql, params = super(CustomJoin, self).as_sql(compiler, connection)
sql = sql.replace('"guardian_userobjectpermission"."object_pk"',
'CAST("guardian_userobjectpermission"."object_pk" AS integer)')
return sql, params
class CustomSQLCompiler(SQLCompiler):
def compile(self, node, select_format=False):
if isinstance(node, Join):
node = CustomJoin(
node.table_name, node.parent_alias, node.table_alias,
node.join_type,
node.join_field, node.nullable, node.filtered_relation
)
return super(CustomSQLCompiler, self).compile(node, select_format)
class CustomQuery(Query):
def get_compiler(self, using=None, connection=None):
original_compiler = super(CustomQuery,
self).get_compiler(using=using, connection=connection)
return CustomSQLCompiler(original_compiler.query,
original_compiler.connection, original_compiler.using)
# return super(CustomQuery, self).get_compiler(using=using,
connection=connection)
class CustomerMemberObjectPermissionQuerySet(CustomerQuerySet):
def __init__(self, model=None, query=None, using=None, hints=None):
if not query:
query = CustomQuery(model)
super(CustomerMemberObjectPermissionQuerySet, self).__init__(
model=model, query=query, using=using, hints=hints
)
class CustomerMemberObjectPermissionManager(CustomerManager,
UserObjectPermissionManager):
def get_queryset(self):
return CustomerMemberObjectPermissionQuerySet(self.model,
using=self._db)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/16055#comment:12>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/067.40cc091896a93c381ca26cf22c8a759b%40djangoproject.com.