Last active
March 6, 2020 17:21
-
-
Save ra0x3/ccb571ffefdee9588d5b146ae3dc3040 to your computer and use it in GitHub Desktop.
A sample model manager demonstrating how joins work
This file contains 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
from peewee_extensions import PeeweeExtensions | |
class BaseManager: | |
def __init__(self, name): | |
self.model_name = name | |
self.exts = PeeweeExtensions(self) | |
self.model = BaseManager.model_for(self.model_name) | |
self.relations = self.model._meta.relations | |
@staticmethod | |
def model_for(modelname): | |
return getattr(models, modelname) | |
@db_rollback() # a simple decorator to rollback operations that generate errors | |
def find(self, params): | |
params = self.exts.normalize_query_parts(params) | |
if self.exts.has_no_includes(params): | |
fields = self.exts.derive_fields(params) | |
clause = self.exts.and_filter(params.query) | |
results = self.model.select(*fields).where(clause).execute() | |
return results | |
join_exprs = [] | |
join_models = [self.model] + [ | |
BaseManager.model_for(name) for name in params.include | |
] | |
join_models = [self.model] | |
for name in params.include: | |
model = BaseManager.model_for(name) | |
if model._meta.relations.has_thru(self.model_name): | |
thru_name = model._meta.relations.thru_for(self.model_name) | |
thru = BaseManager.model_for(thru_name) | |
if not thru in join_models: | |
join_models.append(thru) | |
join_models.append(model) | |
clause = self.exts.and_filter(params.query) | |
query = self.model.select(*join_models).where(clause) | |
thrus_seen = set() | |
for name in params.include: | |
assoc = self.relations.data[name] | |
foreign_model = BaseManager.model_for(name) | |
if assoc.how == "direct": | |
query = query.join(foreign_model).switch(self.model) | |
else: | |
thru_model = BaseManager.model_for(assoc.relation.thru_model) | |
if not thru_model._meta.table_name in thrus_seen: | |
query = query.join(thru_model).where( | |
getattr(self.model, assoc.relation.native_key) | |
== getattr(thru_model, assoc.relation.thru_key) | |
) | |
thrus_seen.add(thru_model._meta.table_name) | |
query = query.join(foreign_model).switch(thru_model) | |
return query.execute() | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment