Introduction

To-do List is a pretty basic example app that is often done as one of the first projects, today we will make it a little more interesting by using few interesting technologies.

As the backend we will use Django and Django Rest Framework, and Alpine.js + Axios to glue it all together easily on the frontend.

What is Alpine.js

A pretty new lightwave framework inspired by Vue.js created last year by Caleb Porzio it gives us reactivity and declarativity of React and Vue, while keeping it light, and in the DOM. It’s described as TailwindCSS for JS. And I pretty much agree with that, using it together with Tailwind is a great boost to productivity when doing front-end because you can stay in one HTML file, and keep writing HTML, CSS, and js.

Axios

It’s an asynchronous HTTP client for JS.

Here is a link to finished project GitHub repo

Starting the app

Let’s start by creating a new virtual environment for our project, and installing required packages, then create a new Django project, and a lists app

pip install Django 
pip install djangorestframework
django-adimn startproject todo_list
cd todo_list
django-admin startapp lists

Then go to settings.py and add lists and django rest framework app to INSTALLED_APPS

INSTALLED_APPS = [
    ...
    ‘rest_framework’,
    ‘lists’,
]

Creating App Models

Let’s create db models for our To-Do App. We are going to define 2 models, a List Model, and a Task model, Each user can create as many lists as he/she wants, and then add multiple tasks to each list.

from django.contrib.auth.models import User
from django.db import models

class List(models.Model):
    title = models.CharField(max_length=75)
    user = models.ForeignKey(User,
                             on_delete=models.CASCADE,
                             related_name=‘lists’)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

class Task(models.Model):
    parent_list = models.ForeignKey(List,
                                    on_delete=models.CASCADE,
                                    related_name=‘tasks’)
    title = models.CharField(max_length=75)
    completed = models.BooleanField(default=False, 
                                    blank=True)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

We created a List model with the title field and relation to the user who created the list.

The Task model, has a relation to List object, title, and boolean for the complete status of the task.

Also for both models also 2 DateTime fields for cerated and updated times.

Go to the admin.py file and register the models in the admin panel

from django.contrib import admin

from .models import List, Task

admin.site.register(List)
admin.site.register(Task)

Run the makemigrations and migrate commands.

python manage.py makemigrations
python manage.py migrateapi

Create API

Create Serializers

Inside the lists app create a new python package (new directory with an empty __init__.py file), and call it api. There create a file serializers.py, views.py, urls.py files inside. Go to serialziers.py and create serializers for the models.

from rest_framework import serializers

from ..models import List, Task

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = (‘title’, ‘completed’, ‘parent_list’)

class ListSerializer(serializers.ModelSerializer):
    tasks = TaskSerializer(many=True, read_only=True)

    class Meta:
        model = List
        fields = (‘title’, ‘tasks’)

Create Viewsets

Now we will create viewsets, that will automatically provide us with Create, Read, Update, and Delete endpoints (CRUD), so we can avoid repetition and writing them for each model. In views.py file create viewsets.

from rest_framework import viewsets
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated

from .serializers import TaskSerializer, ListSerializer
from ..models import Task, List

class ListViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = ListSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        return List.objects.filter(user=user)

        def create(self, request, *args, **kwargs):
        serializer = ListSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(user=request.user)
            return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class TaskViewSet(viewsets.ModelViewSet):
    queryset = Task.objects.all()
    serializer_class = TaskSerializer
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
        user = self.request.user
        return Task.objects.filter(parent_list__user=user)

#django #axios #alpine #tailwindcss #developer

Creating a To-Do List App with Django, DRF, Alpine.JS And Axios
12.10 GEEK