Only the Owner Edits
Part of the Users and Accounts section of Coddy's Django journey. Lesson 11 of 16.
A note's page is safe now, but its edit and delete pages are not: /3/edit/ and /3/delete/ still open any note. Worse, they do not need to be opened at all. A form is a POST request, and anyone can send a POST to /3/delete/ without ever seeing the page.
So the rule is per view, not per page you link to: every view that loads a row by its number decides there who may load it. Look at where the lookup sits in a view that handles both GET and POST:
def ticket_close(request, pk):
ticket = ... # the lookup: it runs for every request
if request.method == "POST":
ticket.closed = True
ticket.save()
return redirect("tickets:list")
return render(request, "tickets/close.html", {"ticket": ticket})The first line runs before the if request.method == "POST" branch. A lookup there that refuses strangers answers them 404 for the GET and for the POST, and nothing is changed.
Challenge
EasyIn notes/views.py, make note_edit and note_delete refuse notes that are not the user's own. Another user's note answers 404 there, for GET and POST, and stays as it was. Your own notes still edit and delete.
Press Run, log in as bob (password coddy-pass-123) and open /1/edit/.
Try it yourself
from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import get_object_or_404, redirect, render
from .forms import NoteForm
from .models import Note
def note_list(request):
notes = Note.objects.filter(owner=request.user)
return render(request, "notes/note_list.html", {"notes": notes})
def note_detail(request, pk):
note = get_object_or_404(Note, pk=pk, owner=request.user)
return render(request, "notes/note_detail.html", {"note": note})
def note_create(request):
if request.method == "POST":
form = NoteForm(request.POST)
if form.is_valid():
note = form.save(commit=False)
note.owner = request.user
note.save()
return redirect("notes:detail", pk=note.pk)
else:
form = NoteForm()
return render(request, "notes/note_form.html", {"form": form})
def note_edit(request, pk):
note = get_object_or_404(Note, pk=pk)
if request.method == "POST":
form = NoteForm(request.POST, instance=note)
if form.is_valid():
form.save()
return redirect("notes:detail", pk=note.pk)
else:
form = NoteForm(instance=note)
return render(request, "notes/note_form.html", {"form": form, "note": note})
def note_delete(request, pk):
note = get_object_or_404(Note, pk=pk)
if request.method == "POST":
note.delete()
return redirect("notes:list")
return render(request, "notes/note_confirm_delete.html", {"note": note})
@login_not_required
def signup(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user)
return redirect("notes:list")
else:
form = UserCreationForm()
return render(request, "notes/signup.html", {"form": form})
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Users and Accounts
Practice on your own: Django playground