Last active
June 8, 2021 16:42
-
-
Save Apkawa/e30909696ec614d8fc65 to your computer and use it in GitHub Desktop.
Django patch for join with extra
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from .queryset import ExtraJoinQuerySet | |
class ModelQuerySet(ExtraJoinQuerySet): | |
def attach_useful_vote(self, user=None): | |
return self.extra(select={"field": "joined_table.field"}, | |
join=[ | |
""" | |
JOIN (SELECT rel_id, field FROM subselect_table) AS joined_table ON table.id = joined_table.rel_id | |
""" | |
], | |
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
import new | |
from functools import update_wrapper | |
from django.db.models.query import QuerySet | |
from django.db.models.sql.query import Query | |
def replace_method(method, func): | |
instance = method.im_self | |
method_name = method.__name__ | |
orig_method = method | |
func.super = orig_method | |
update_wrapper(func, method) | |
setattr(instance, method_name, new.instancemethod(func, instance, instance.__class__)) | |
def SQLCompiler__get_from_clause(self): | |
from_, f_params = SQLCompiler__get_from_clause.super() | |
if getattr(self.query, "extra_join", None): | |
from_.extend(self.query.extra_join) | |
return from_, f_params | |
class ExtraJoinQuery(Query): | |
extra_join = None | |
def clone(self, **kwargs): | |
q = super(ExtraJoinQuery, self).clone(**kwargs) | |
q.extra_join = self.extra_join | |
return q | |
def get_compiler(self, using=None, connection=None): | |
compiler = super(ExtraJoinQuery, self).get_compiler(using=using, connection=connection) | |
replace_method(compiler.get_from_clause, SQLCompiler__get_from_clause) | |
return compiler | |
class ExtraJoinQuerySet(QuerySet): | |
def __init__(self, model=None, query=None, using=None): | |
super(ExtraJoinQuerySet, self).__init__(model, query, using) | |
self.query = query or ExtraJoinQuery(self.model) | |
def extra(self, **kwargs): | |
sql_join = kwargs.pop("join", []) | |
extra_join = getattr(self.query, "extra_join", None) or [] | |
extra_join.extend(sql_join) | |
setattr(self.query, "extra_join", extra_join) | |
return super(ExtraJoinQuerySet, self).extra(**kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment