Menu
CoddyTech

只有所有者可以编辑

本课属于 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,数据也不会发生变化。

challenge icon

挑战

简单

在 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})
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

用户和账户中的所有课

自己练习: Django 在线编辑器