Menu
CoddyTech

A Public Link

Part of the Users and Accounts section of Coddy's Django journey. Lesson 16 of 16.

A shared note needs an address anyone can open, signed in or not, that shows the note and nothing else. The owner's page has Edit and Delete; this page must not.

You have used every piece already. Ask the questions you answered before: in a private site, who may open this page? Which notes may it find, and what does it answer for the others? Which template, so the page cannot link to Edit and Delete? A link is safe to hand out only when the server checks it on every request.

Test it as three people: the owner, another user, and a visitor who is logged out.

challenge icon

Challenge

Medium
  • A public page at /shared/<id>/, named shared, that anyone can open. It shows a shared note's title, body, and Shared by with the owner's username.
  • A private note answers 404 there, for everyone.
  • No Edit or Delete links on it.
  • On a shared note's own page, a link Share link to it.

Press Run, log out and open /shared/2/.

Try it yourself

from django.contrib.auth import login
from django.contrib.auth.decorators import login_not_required, permission_required
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
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, owner=request.user)
    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, owner=request.user)
    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})


def stats(request):
    if not request.user.is_staff:
        raise PermissionDenied
    context = {"user_count": User.objects.count(), "note_count": Note.objects.count()}
    return render(request, "notes/stats.html", context)


@permission_required("notes.view_note", raise_exception=True)
def all_notes(request):
    notes = Note.objects.select_related("owner")
    return render(request, "notes/all_notes.html", {"notes": notes})


def profile(request):
    note_count = request.user.notes.count()
    return render(request, "notes/profile.html", {"note_count": note_count})
quiz iconTest yourself

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