Chỉ chủ sở hữu mới chỉnh sửa
Thuộc phần Người dùng và tài khoản trong hành trình Django của Coddy. Bài học 11 trên 16.
Trang của một ghi chú hiện đã an toàn, nhưng trang chỉnh sửa và xóa thì chưa: /3/edit/ và /3/delete/ vẫn mở được bất kỳ ghi chú nào. Tệ hơn nữa, không cần mở các trang đó. Biểu mẫu gửi yêu cầu POST, và bất kỳ ai cũng có thể gửi yêu cầu POST đến /3/delete/ mà không cần xem trang.
Vì vậy, quy tắc áp dụng cho từng view, không chỉ cho trang mà bạn liên kết đến: mỗi view tải một hàng theo số của hàng đó sẽ quyết định tại đó ai được phép tải hàng ấy. Hãy xem vị trí của thao tác tra cứu trong một view xử lý cả GET lẫn POST:
def ticket_close(request, pk):
ticket = ... # thao tác tra cứu: chạy với mọi yêu cầu
if request.method == "POST":
ticket.closed = True
ticket.save()
return redirect("tickets:list")
return render(request, "tickets/close.html", {"ticket": ticket})Dòng đầu tiên chạy trước nhánh if request.method == "POST". Nếu thao tác tra cứu đó cũng kiểm tra chủ sở hữu, người lạ sẽ nhận lỗi 404 cho cả GET lẫn POST, và không có gì thay đổi.
Thử thách
DễTrong notes/views.py, hãy chỉnh sửa note_edit và note_delete để từ chối xử lý ghi chú không thuộc về người dùng hiện tại. Ghi chú của người khác sẽ trả về 404 ở đó, với cả GET lẫn POST, và vẫn giữ nguyên trạng. Bạn vẫn có thể chỉnh sửa và xóa ghi chú của mình.
Đăng nhập bằng tài khoản bob (mật khẩu coddy-pass-123) rồi mở /1/edit/: 404 Không tìm thấy trang.
Tự làm thử
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})
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Người dùng và tài khoản
3Dữ liệu của riêng bạn
Mỗi ghi chú đều có chủ sở hữuChỉ ghi chú của bạnTự luyện tập: Playground Django