Last active
January 30, 2019 18:55
-
-
Save simonw/dd0da256716c0b0ec4efe12a81caec45 to your computer and use it in GitHub Desktop.
combined_recent() function for union across querysets returning most recent objects. See https://simonwillison.net/2018/Mar/25/combined-recent-additions/
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 django.db.models import Value, CharField | |
def combined_recent(limit, **kwargs): | |
datetime_field = kwargs.pop('datetime_field', 'created') | |
querysets = [] | |
for key, queryset in kwargs.items(): | |
querysets.append( | |
queryset.annotate( | |
recent_changes_type=Value( | |
key, output_field=CharField() | |
) | |
).values('pk', 'recent_changes_type', datetime_field) | |
) | |
union_qs = querysets[0].union(*querysets[1:]) | |
records = [] | |
for row in union_qs.order_by('-{}'.format(datetime_field))[:limit]: | |
records.append({ | |
'type': row['recent_changes_type'], | |
'when': row[datetime_field], | |
'pk': row['pk'] | |
}) | |
# Now we bulk-load each object type in turn | |
to_load = {} | |
for record in records: | |
to_load.setdefault(record['type'], []).append(record['pk']) | |
fetched = {} | |
for key, pks in to_load.items(): | |
for item in kwargs[key].filter(pk__in=pks): | |
fetched[(key, item.pk)] = item | |
# Annotate 'records' with loaded objects | |
for record in records: | |
record['object'] = fetched[(record['type'], record['pk'])] | |
return records | |
# recent = combined_recent( | |
# 20, | |
# entry=Entry.objects.all(), | |
# photo=Photo.objects.all(), | |
# ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment