Đây là 4 helper hay dùng nhất trong view, làm code ngắn và nhất quán.
get_object_or_404(Model, *lookup) gọi .get(), nếu DoesNotExist thì raise Http404 → Django tự trả 404 page, đỡ phải try/except lặp đi lặp lại. Http404 là exception built-in; raise ở đâu thì Django cũng chặn được và render 404.html (hoặc handler404 custom). redirect(to, args, **kwargs) return HttpResponseRedirect — to có thể là URL string, URL name, hoặc model instance (Django sẽ gọi .get_absolute_url()). reverse('namespace:name', kwargs={...}) đảo ngược URL name thành URL string — dùng trong code Python; {% url %} là phiên bản template tag.
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.http import Http404
def edit_post(request, slug):
post = get_object_or_404(Post, slug=slug, author=request.user)
if post.locked:
raise Http404('Post is locked') # hoặc redirect kèm message
if request.method == 'POST':
# ... process form ...
return redirect('blog:post-detail', slug=post.slug)
# ↑ tương đương: redirect(reverse('blog:post-detail', kwargs={'slug': post.slug}))
return render(request, 'blog/edit.html', {'post': post})Đừng render() form sau khi mutate state — luôn dùng pattern POST → redirect → GET, nếu không user back/refresh sẽ resubmit form.
Và get_object_or_404 chỉ nên dùng cho object user có quyền thấy; check permission trước hoặc thêm filter vào lookup (vd author=request.user) để tránh leak existence — sự khác biệt 404 vs 403 với object private cũng có thể tiết lộ thông tin.
These four are the most-used view helpers, keeping code short and consistent:
get_object_or_404(Model,lookup)** — calls.get(), raisesHttp404onDoesNotExist→ Django returns the 404 page. Saves repetitivetry/except.Http404— built-in exception; raising it anywhere lets Django intercept → render404.html(or your customhandler404).- *
redirect(to,args, kwargs) — returnsHttpResponseRedirect.toaccepts a URL string, URL name, or a model instance (it calls.get_absolute_url()). reverse('namespace:name', kwargs={...})— inverts a URL name → URL string. Use it in Python;{% url %}is the template counterpart.
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.http import Http404
def edit_post(request, slug):
post = get_object_or_404(Post, slug=slug, author=request.user)
if post.locked:
raise Http404('Post is locked') # or redirect with a message
if request.method == 'POST':
# ... process form ...
return redirect('blog:post-detail', slug=post.slug)
# ↑ same as: redirect(reverse('blog:post-detail', kwargs={'slug': post.slug}))
return render(request, 'blog/edit.html', {'post': post})Pitfall: Do not render() the form after mutating state — use the POST → redirect → GET pattern, otherwise back/refresh will resubmit.
And use get_object_or_404 only for objects the user is allowed to see; check permissions first or add a filter into the lookup (e.g. author=request.user) to avoid existence leaks (404 vs 403 on private objects can leak info).