You can create a database view that will contain all Page
columns alongside with with necessary latest Post
columns:
CREATE VIEW `testapp_pagewithrecentpost` AS
SELECT testapp_page.*, testapp_post.* -- I suggest as few post columns as possible here
FROM `testapp_page` LEFT JOIN `testapp_page`
ON test_page.id = test_post.page_id
AND test_post.post_time =
( SELECT MAX(test_post.post_time)
FROM test_post WHERE test_page.id = test_post.page_id );
Then you need to create a model with flag managed = False
(so that manage.py sync
won't break). You can also use inheritance from abstract Model to avoid column duplication:
class PageWithRecentPost(models.Model): # Or extend abstract BasePost ?
# Page columns goes here
# Post columns goes here
# We use LEFT JOIN, so all columns from the
# 'post' model will need blank=True, null=True
class Meta:
managed = False # Django will not handle creation/reset automatically
By doing that you can do what you initially wanted, so fetch from both tables in just one query:
pages_with_recent_post = PageWithRecentPost.objects.filter(...)
for page in pages_with_recent_post:
print page.name # Page column
print page.post_time # Post column
However this approach is not drawback free:
- It's very DB engine-specific
- You'll need to add VIEW creation SQL to your project
- If your models are complex it's very likely that you'll need to resolve table column name clashes.
- Model based on a database view will very likely be read-only (INSERT/UPDATE will fail).
- It adds complexity to your project. Allowing for multiple queries is a definitely simpler solution.
- Changes in
Page/Post
will require re-creating the view.