Goal for this part
Replace placeholder text with a public feed and a permalink for each post. Guests can read. Writes wait until login exists.
Concepts
A social feed is a query, not a magic algorithm. For now the public home page is “latest posts from everyone,” newest first, with author name and relative time. The following timeline comes in part 10. select_related and prefetch_related keep that query from becoming N+1 once avatars and like counts appear.
Walkthrough
# posts/views.py
from django.shortcuts import get_object_or_404, render
from .models import Post
def feed(request):
posts = (
Post.objects.select_related("author", "author__profile")
.prefetch_related("likes", "comments")
)
return render(request, "posts/feed.html", {"posts": posts})
def detail(request, slug):
post = get_object_or_404(
Post.objects.select_related("author", "author__profile"),
slug=slug,
)
return render(request, "posts/detail.html", {"post": post})Each card links to the author profile (stub for now) and to posts:detail. Keep the body to 500 characters — Westloop is a neighborhood update, not a blog CMS.
How to run it and what you should see
Open /. Seeded posts from Ada and Grace should appear as cards. Click a timestamp or “Open” link and land on /p/<slug>/ with the full body and a comment list heading (empty until part 9).
Common mistakes
Forgetting select_related("author__profile") will query once per card once avatars exist. A missing slug in the seed data 404s the detail page. Do not put compose-box HTML on this snapshot — guests should not see a form that 403s.
Try this
Add a like count and comment count to each card using the prefetched relations. Confirm the home page still does a handful of SQL queries, not one per post, by watching django.db.backends logging.