Posts CRUD
Goal for this part
Let authors manage their own posts from the public site. You will add detail, create, update, and delete views—typically Django class-based views—with login and ownership checks.
After this snapshot, Campus Press supports a full create/read/update/delete loop for blog posts without using the admin for everyday writing.
What you should already know
You should understand the Post model, authentication, and login_required / mixins. Reading class-based view docs helps, but the snapshot keeps each class small and focused.
Ownership matters: only the author should update or delete a post. Mixing in user checks prevents one account from editing another’s work.
Concepts: CreateView, UpdateView, DeleteView
Class-based views supply a pattern for forms tied to models. You set model, fields, and success_url (or get_absolute_url on the model). LoginRequiredMixin and UserPassesTestMixin guard write operations.
On create, set form.instance.author = self.request.user in form_valid so the foreign key is always the logged-in user.
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import CreateView, UpdateView, DeleteView
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ["title", "content"]
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ["title", "content"]
def test_func(self):
return self.get_object().author == self.request.user
Walkthrough: detail links and get_absolute_url
Add get_absolute_url on Post so create/update can redirect to the detail page. Link titles on home to that detail route. DeleteView should confirm before destroying a row.
Wire URL patterns with <int:pk> converters for detail, update, and delete.
from django.urls import reverse
class Post(models.Model):
# ... fields ...
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.pk})
How to run it and what you should see
Run 09-Posts-CRUD, log in, create a post, edit it, open its detail page, then delete it. Try editing someone else’s post while logged in as a second user—you should be denied.
git clone https://github.com/michaeldunga1/fcc-django-blog.git
cd fcc-django-blog/09-Posts-CRUD
python3 -m venv .venv
source .venv/bin/activate
pip install -r ../requirements.txt
python manage.py migrate
python manage.py runserver
Common mistakes and troubleshooting
If author is null on create, you forgot to set it in form_valid. If update allows any user, test_func is missing or always returns True. TemplateDoesNotExist for post_form.html means the expected CBV template name is not in the snapshot path Django searches.
Try this
Create two users and two posts. Confirm each user only sees edit/delete controls for their own posts if the templates gate those links on user == post.author.
- CBVs reduce boilerplate for standard model forms
- Always set author from
request.user - Ownership checks belong in the view, not only in the template
Next: Pagination
Comments
One comment per signed-in account. Comments are saved with this page’s URL.