只有所有者可以编辑
本课属于 Coddy Django 学习旅程的“用户和账户”单元。第 11 课,共 16 课。
现在,笔记的页面已经受到保护,但编辑和删除页面还没有:/3/edit/ 和 /3/delete/ 仍然可以打开任意笔记。更糟的是,根本不需要打开这些页面。表单会发送 POST 请求,任何人都可以向 /3/delete/ 发送 POST 请求,而无需查看该页面。
所以,规则适用于每个视图,而不只是你链接到的页面:每个按编号加载一行数据的视图,都要在视图中决定谁可以加载它。看看同时处理 GET 和 POST 的视图中,查询操作的位置:
def ticket_close(request, pk):
ticket = ... # 查询:每次请求都会执行
if request.method == "POST":
ticket.closed = True
ticket.save()
return redirect("tickets:list")
return render(request, "tickets/close.html", {"ticket": ticket})第一行会在 if request.method == "POST" 分支之前运行。如果查询操作也会检查所有者,那么陌生人发送 GET 或 POST 请求都会收到 404,数据也不会发生变化。
挑战
简单在 notes/views.py 中,让 note_edit 和 note_delete 拒绝处理不属于当前用户的笔记。对于其他用户的笔记,GET 和 POST 请求都会返回 404,并且笔记保持原样。你自己的笔记仍然可以编辑和删除。
以 bob 身份登录(密码为 coddy-pass-123),然后打开 /1/edit/:404 页面未找到。
亲手试试
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})
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
用户和账户中的所有课
自己练习: Django 在线编辑器