Skip to content

Instantly share code, notes, and snippets.

@simonw simonw/combined_recent.py
Last active Jan 30, 2019

Embed
What would you like to do?
combined_recent() function for union across querysets returning most recent objects. See https://simonwillison.net/2018/Mar/25/combined-recent-additions/
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
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.