How to Build a Notes App Using Django

how to build a notes app using django

In this tutorial, we will be building a minimalistic note-taking app using Django. The app will utilize basic crud operations that are create, retrieve, update, and delete. To begin first let’s first install Django which will be our primary web server. To do so let’s run the command below. Here are a few screenshots of the finished application.

Install django

pip3 install django

After Django is successfully installed, run the commands below to create our project.

django-admin startproject django_notes

After the above command is executed successfully, a folder called django_notes will be created, cd into the directory, and then run the command below which will create our application called notes.

python3 manage.py startapp notes

Next, we need to register our app into our project, to do so add the following in the settings.py file in the django_notes folder.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'notes',
]

Next create routes for our notes app, to do so add the following in the urls.py in the django_notes folder.

from django.contrib import admin
from django.urls import path,include 

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('notes.urls')),
]

Create models

Now we need to make models for our notes application, inside the models.py file inside the notes folder add the following.

from django.db import models
from django.utils import timezone 

class Notes(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(max_length=30000)
    upload_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.title

Create forms

Next, we need to create an upload form that will inherit from the model created above. Inside the notes folder create a file called forms.py and add the following.

from django import forms 
from . models import Notes

class NotesUploadForm(forms.ModelForm):

    class Meta:
        model = Notes
        fields = ["title", "description"]

Create views

Let’s now create views for our application but first let’s import some modules in the views.py file inside the notes folder.

from django.shortcuts import render, redirect,get_object_or_404
from django.views.generic import DetailView, DeleteView, UpdateView, ListView, CreateView
from . models import Notes
from . forms import NotesUploadForm

Now let’s create a view to handle the notes upload functionality.

class NoteCreateView(CreateView):
    model = Notes
    success_url = "/"
    template_name = 'notes/note_create.html'
    fields = ['title', 'description']

Let’s now create another view to display the uploaded notes.

class NoteListView(ListView):
    model = Notes
    template_name = 'notes/note_list.html'
    context_object_name = 'notes'
    ordering = ['-upload_date']

Search functionality is crucial in any web application so here is our simple implementation as shown below.

def search(request):
    if request.method == "POST":
        query = request.POST.get('title', None)
        if query:
            results = Notes.objects.filter(title__contains=query)
            return render(request, 'notes/search.html',{'notes':results})
    
    return render(request, 'notes/search.html')

Next, we need to have a way to delete notes we don’t need anymore. Here is a view to handle delete operations.

class NoteDeleteView(DeleteView):
    template_name = "notes/note_delete.html"
    success_url = "/"
    model = Notes

We then need a way to update notes once in a while to enable the user to do so let’s create a view to handle that.


def note_update(request, pk):
    obj = get_object_or_404(Notes, pk=pk)
    form = NotesUploadForm(request.POST or None, instance=obj)
    if form.is_valid():
        form.save()
        return redirect('/')
    context = {
        'form':form
    }
    return render(request, 'notes/note_update.html',context)

Finally, let’s create a view to see the notes in detail.

class NoteDetailView(DetailView):
    template_name = "notes/note_detail.html"
    model = Notes

Templates

Now we need to render our application on a web browser, to do so create a folder called templates inside the notes folder and then create a file called base.html. [notes/templates/notes/base.html]

Above we have created a base template from which all the other templates in the application will inherit. Inside the base.html add the following.

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
          <a class="navbar-brand" href="{% url 'note-list' %}">Notes App</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="navbar-nav">
      
            <div class="nav-item ml-auto">
                <a class="nav-item nav-link" href="{% url 'search'%}">Search</a>
            </div>
            <div class="nav-item">
                <a class="nav-item nav-link" href="{% url 'note-create' %}">New Note</a>
            </div>
      
          </div>
        </div>
      </nav>
      
  
     <div class="container" id="app">
        {% block content %}
        {% endblock %}
    </div>
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
</body>
</html>

Next, we need to create a template where users can upload notes, create a file called note_create.html and add the code below.

{% extends 'notes/base.html' %}

{% block content %}
</br>
<div class="container">
  <div class="row justify-content-center">
    <div class="col-md-6">
      <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <h1 class="text-center mb-4">Upload a Note</h1>
        {{ form.as_p }}
        <button class="btn btn-outline-info btn-block mt-4" type="submit">Upload</button>
      </form>
    </div>
  </div>
</div>
{% endblock content %}

Let’s now create a template to display the uploaded notes. Create a file called note_list.html and add the code below.

{% extends 'notes/base.html' %}

{% block content %}
<div class="container py-5">
    <div class="row row-cols-1 row-cols-md-3 g-4">
        {% for item in notes %}
        <div class="col">
            <div class="card h-100">
                <div class="card-body">
                    <h5 class="card-title"> <a href="{% url 'note-detail' item.id %}">{{ item.title }}</a></h5>
                    <p class="card-text">{{ item.description|truncatechars:100 }}</p>
                </div>
                <div class="card-footer text-muted">
                    {{ item.upload_date|date:"F d, Y" }}
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
</div>
{% endblock content %}

Next is the search template where users can search their notes, create a template called search.html and add the code below.

{% extends 'notes/base.html'%}
{% block content %}
    <div class="center_journal">
        <h1>Search </h1>
    </div>
    <div>
        <form method="POST">
            {% csrf_token %}
            <div class="input-group">
                <div class="input-group-prepend">
                <span class="input-group-text"></span>
                </div>
                <input type="text" class="form-control" name="title">
                <button type="submit" class="btn btn-dark">Search</button>
            </div>


        </form>
    </div>
    </br>
    
    <div class="container py-5">
      <div class="row row-cols-1 row-cols-md-3 g-4">
          {% for item in notes %}
          <div class="col">
              <div class="card h-100">
                  <div class="card-body">
                      <h5 class="card-title"> <a href="{% url 'note-detail' item.id %}">{{ item.title }}</a></h5>
                      <p class="card-text">{{ item.description|truncatechars:100 }}</p>
                  </div>
                  <div class="card-footer text-muted">
                      {{ item.upload_date|date:"F d, Y" }}
                  </div>
              </div>
          </div>
          {% endfor %}
      </div>
  </div>
{% endblock content %}

Next is the update template where users can update their already uploaded notes, create a file called note_update.html and upload the code below.

{% extends 'notes/base.html' %}
{% block content %}
</br>
<div>
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <h1>Upload a video</h1>
            {{ form.as_p }}
        <button class="btn btn-outline-info" type="submit">Upload</button>

    </form>
</div>
{% endblock content %}

We then need a way for users to delete notes they don’t need anymore, to do so create a file called note_delete.html and add the code below.

{% extends 'notes/base.html'%}
{% block content %}
    </br>
    <div style="margin-top: 1%;">
        <form method="POST">
            {% csrf_token %}
            <h3>Are you sure you want to delete the video {{ object.title }} ?</h3>
            <button type="submit" class="btn btn-primary">Confirm Delete</button>
        </form>
    </div>
{% endblock content %}

Finally, we need a way to see notes in a detailed form, to do so create a file called note_detail.html and add the code below.

{% extends 'notes/base.html' %}

{% block content %}
<div class="container my-5">
  <div class="card">
    <div class="card-header">
      <h4 class="card-title">{{ object.title }}</h4>
    </div>
    <div class="card-body">
      <p class="card-text">{{ object.description }}</p>
      <p class="card-text">Upload date: {{ object.upload_date }}</p>
    </div>
  </div>
  <div>
    <a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'note-update' object.id %}">Update</a>
    <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'note-delete' object.id %}">Delete</a>
</div>
</div>
{% endblock content %}

Create routes

Now let’s create routes for our notes app, create a file in the notes app called urls.py and add the code below.

from django.urls import path 
from . import views 
from . views import (
    NoteCreateView,
    note_update,
    NoteDeleteView,
    NoteListView,
    NoteDetailView,
)
urlpatterns = [
    path('',NoteListView.as_view(),name="note-list"),
    path('search',views.search,name="search"),
    path('create',NoteCreateView.as_view(),name="note-create"),
    path('note_detail/<int:pk>/',NoteDetailView.as_view(),name="note-detail"),
    path('update/<int:pk>/',views.note_update, name="note-update"),
    path('delete/<int:pk>/',NoteDeleteView.as_view(), name="note-delete"),
]

Now our application is almost finished, let’s run a few commands to get the server up and running.

Run the command below to create the database as outlined in the models.py file.

python3 manage.py makemigrations

Next, run the command below to migrate the data.

python3 manage.py migrate

Finally, run the command below which will open a browser at this address. [http://127.0.0.1:80000]

python3 manage.py runserver

After the above command is executed if all goes well the server should be up and running.

There you have it. Thanks for reading.

Leave a Comment

Your email address will not be published. Required fields are marked *