Home

Boilerplate: Make A Basic Django App With The Ability To Create, Read, Update, and Delete Content From A Protected Web Interface

Introduction

Boilerplate Steps

  1. Make sure you've started the Python venv and are in the directory with: manage.py

    TODO: Write up how to make sure you're in the proper venv

  2. Create the app

    terminal commands
    python manage.py startapp notes
  3. Make the templates directory:

    terminal commands
    mkdir -p notes/templates/notes
  4. The INSTALLED_APPS = [] section of site_files/settings.py to add:

    python
    "notes.app.NotesConfig",

    It should look like this when you're done:

    site_files/settings.py - replacement lines
    INSTALLED_APPS = [
        "django.contrib.admin",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",
        "django.contrib.messages",
        "django.contrib.staticfiles",
        "notes.apps.NotesConfig",
    ]
  5. Update the top level urls patterns

    site_files/urls.py - full content replacement
    from django.contrib import admin
    from django.urls import path
    from django.urls import include
    
    urlpatterns = [
        path("accounts/", include("django.contrib.auth.urls")),
        path("admin/", admin.site.urls),
        path("notes/", include("notes.urls")),
    ]
  6. Create the Note model

    notes/models.py - full content replacement
    from django.db import models
    
    class Note(models.Model):
        note_title = models.CharField(max_length=200)
        note_text = models.TextField()
        created_at = models.DateTimeField(auto_now_add=True)
        updated_at = models.DateTimeField(auto_now=True)
    
        def __str__(self):
            return self.note_title
  7. Make the "notes/urls.py" file:

    create new file: notes/urls.py
    from django.urls import path
    
    from . import views
    
    app_name = "notes"
    urlpatterns = [
        path("", views.index, name="index"),
        path("create/", views.create, name="create"),
        path("<int:pk>/", views.view, name="view"),
        path("<int:pk>/edit/", views.edit, name="edit"),
        path("<int:pk>/delete/", views.delete, name="delete"),
    ]
  8. Add the admin for the notes page

    notes/admin.py - full content replacement
    from django.contrib import admin
    
    from .models import Note
    
    admin.site.register(Note)
  9. Add the functions to: notes/views.py

    notes/views.py - full content replacement
    from django.contrib.auth.decorators import login_required
    from django.http import HttpResponseRedirect
    from django.shortcuts import get_object_or_404, render
    
    from .models import Note 
    from .forms import NoteForm
    
    def index(request):
        notes_list = Note.objects.order_by("created_at")
        context = {"notes_list": notes_list}
        return render(request, "notes/index.html", context)
    
    @login_required
    def create(request):
        if request.method == "POST":
            form = NoteForm(request.POST)
            if form.is_valid():
                form.save()
                # TODO: Update this url to be automatic 
                return HttpResponseRedirect("/notes/")
        else:
            form = NoteForm()
            context = { "form": form }
            return render(request, "notes/create.html", context)
    
    @login_required
    def delete(request, pk):
        note = get_object_or_404(Note, pk=pk)
        if request.method == "POST":
            note.delete()
            # TODO: set this url automatically
            return HttpResponseRedirect("/notes/")
        else:
            context = { "note": note }
            return render(request, "notes/delete.html", context)
    
    @login_required
    def edit(request, pk):
        note = get_object_or_404(Note, pk=pk)
        if request.method == "POST":
            form = NoteForm(request.POST)
            if form.is_valid():
                note.note_text = form.cleaned_data["note_text"]
                note.note_title = form.cleaned_data["note_title"]
                note.save()
                # TODO: Figure out how to make this redirect URL automatically
                return HttpResponseRedirect(f"/notes/{pk}/")
        else:
            form = NoteForm(instance=note)
            context = { "form": form, "note": note }
            return render(request, "notes/edit.html", context)
    
    def view(request, pk):
        note = get_object_or_404(Note, pk=pk)
        return render(request, "notes/view.html", {"note": note})
  10. Add the forms.py file:

    notes/forms.py - new file to create
    from django.forms import ModelForm
    
    from .models import Note
    
    class NoteForm(ModelForm):
        class Meta:
            model = Note 
            fields = ["note_title", "note_text"]
  11. Create the index.html template

    notes/templates/notes/index.html - new file to create
    <!DOCTYPE html>
    <html>
    <body>
      {% include 'registration/login_status.html' %}
      <div>
          Notes
      </div>
      <hr />
      <h1>Notes</h1>
      <ul>
        {% for note in notes_list %}
          <li>
            {{ note.note_title }}
            <a href="{% url 'notes:view' note.id %}">view</a>
          </li>
        {% endfor %}
      </ul> 
      <hr />
      <div><a href="{% url 'notes:create' %}">Create A Note</a></div>
    </body>
    </html>
  12. Create the view.html template

    notes/templates/notes/view.html - new file to create
    <!DOCTYPE html>
    <html>
    <body>
      {% include 'registration/login_status.html' %}
      <div>
          <a href="{% url 'notes:index' %}">Notes</a>
      </div>
      <hr />
      <h1>Note Detail</h1>
      <div>{{ note.note_title }}</div>
        <div><pre>{{ note.note_text }}</pre></div>
      <div>
        <div>Created: {{ note.created_at }}</div>
        <div>Updated: {{ note.updated_at }}</div>
      </div>
      <hr />
      <div>
        <a href="{% url 'notes:edit' note.id %}">Edit note</a>
          - 
        <a href="{% url 'notes:delete' note.id %}">Delete note</a>
      </div>
    </body>
    </html>
  13. Create the create.html template

    notes/templates/notes/create.html - new file content
    <!DOCTYPE html>
    <html>
    <body>
      {% include 'registration/login_status.html' %}
      <div>
          <a href="{% url 'notes:index' %}">Notes</a>
      </div>
      <hr />
      <h1>Create A Note</h1>
        <form action="{% url 'notes:create' %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Create Note">
      </body>
    </html>
  14. Create the edit.html template

    notes/templates/notes/edit.html - new file content
    <!DOCTYPE html>
    <html>
    <body>
      {% include 'registration/login_status.html' %}
      <div>
          <a href="{% url 'notes:index' %}">Notes</a>
      </div>
      <hr />
      <h1>Edit Note</h1>
        <form action="{% url 'notes:edit' note.id %}" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Update">
      </form>
    </body>
    </html>
  15. Create the delete.html template

    notes/templates/notes/delete.html - new file content
    <!DOCTYPE html>
    <html>
    <body>
        {% include 'registration/login_status.html' %}
        <div>
          <a href="{% url 'notes:index' %}">Notes</a>
        </div>
        <hr />
        <h1>Confirm You Want To Delete The Note</h1>
        <div>{{ note.note_title }}</div>
        <div><pre>{{ note.note_text }}</pre></div>
        <div>Created: {{ note.created_at }}</div>
        <div>Updated: {{ note.updated_at }}</div>
        <hr />
        <form action="{% url 'notes:delete' note.id %}" method="post">
            {% csrf_token %}
            <input type="submit" value="Delete">
        </form>
    </body>
    </html>
  16. Run the migrations

    terminal commands
    python manage.py makemigrations notes
    python manage.py migrate
  17. Start the server:

    terminal commands
    python manage.py runserver
  18. Visit the page:

~ fin ~