Building a TODO App with Python and React

This tutorial will guide you on how to build a simple To-Do application using Python and React. We will be using Python's Django framework for the backend and React for the frontend.

Prerequisites

To follow this tutorial, you should have:

  • Basic knowledge of Python and JavaScript.
  • Node.js and npm installed on your machine.
  • Python 3.8 or newer installed on your machine.
  • Django installed in your Python environment.
  • An Integrated Development Environment (IDE) like Visual Studio Code.

Let's start!

Backend Setup (Python with Django)

Step 1: Setup a new Django project

In your terminal, navigate to the location where you want your project to be, and run the following commands:

django-admin startproject todo
cd todo

This will create a new Django project named 'todo'.

Step 2: Create a new Django app

Next, create a new Django application within your project.

python manage.py startapp tasks

This will create a new Django application named 'tasks'.

Step 3: Define your models

In tasks/models.py, define your Task model:

from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=200)
    completed = models.BooleanField(default=False)

    def __str__(self):
        return self.title

After defining the model, apply the migrations by running:

python manage.py makemigrations
python manage.py migrate

Step 4: Create a Serializer

To convert complex datatypes, such as querysets and model instances, to native Python datatypes that can then be easily rendered into JSON, XML or other content types, we use Serializers.

In tasks/serializers.py, write the following code:

from rest_framework import serializers
from .models import Task

class TaskSerializer(serializers.ModelSerializer):

    class Meta:
        model = Task
        fields = ('id', 'title', 'completed')

Step 5: Define your Views

In tasks/views.py, write the following code:

from django.shortcuts import render
from rest_framework import viewsets
from .models import Task
from .serializers import TaskSerializer

class TaskView(viewsets.ModelViewSet):
    serializer_class = TaskSerializer
    queryset = Task.objects.all()

Step 6: Define your URLs

In tasks/urls.py, write the following code:

from django.urls import path
from .views import TaskView
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'', TaskView, basename='tasks')
urlpatterns = router.urls

Finally, include the tasks URLs in the project's URL configuration. In todo/urls.py:

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

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

Frontend Setup (React)

Step 1: Create a new React app

In your terminal, navigate to the location where you want your project to be, and run the following command:

npx create-react-app todo-frontend
cd todo-frontend

Step 2: Install necessary dependencies

We are going to use Axios for HTTP requests and Bootstrap for styling.

npm install axios react-bootstrap bootstrap

Step 3: Create a new component for displaying tasks

Create a new file Tasks.js in the src directory and write the following code:

import React, { Component } from 'react';
import axios from 'axios';

class Tasks extends Component {
  constructor() {
    super();
    this.state = {
      tasks: []
    };
  }

  componentDidMount() {
    this.getTasks();
  }

  getTasks() {
    axios.get('/api/')
      .then(res => {
        this.setState({ tasks: res.data });
      })
      .catch(err => {
        console.log(err);
      });
  }

  render() {
    return (
      <div>
        {this.state.tasks.map(item => (
          <h1 key={item.id}>{item.title}</h1>
        ))}
      </div>
    );
  }
}

export default Tasks;

Step 4: Create a new component for adding tasks

Create a new file TaskForm.js in the src directory and write the following code:

import React, { Component } from 'react';
import axios from 'axios';

class TaskForm extends Component {
  constructor() {
    super();
    this.state = {
      title: ''
    };
  }

  handleChange = (e) => {
    this.setState({
      title: e.target.value
    });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    axios.post('/api/', { title: this.state.title })
      .then(res => {
        console.log(res);
        this.setState({
          title: ''
        });
        this.props.refreshTasks();
      })
      .catch(err => {
        console.log(err);
      });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="text" 
               name="title" 
               value={this.state.title} 
               onChange={this.handleChange} 
               placeholder="Add task..." />
        <button type="submit">Add</button>
      </form>
    );
  }
}

export default TaskForm;

Step 5: Update App.js to use these components

In your App.js, include the TaskForm and Tasks components:

import React, { Component } from 'react';
import Tasks from './Tasks';
import TaskForm from './TaskForm';

class App extends Component {
  render() {
    return (
      <div className="App">
        <TaskForm />
        <Tasks />
      </div>
    );
  }
}

export default App;

Finally, to connect your backend with frontend, use Django CORS headers in your Django application to handle the CORS headers, as both your frontend and backend are going to run on different servers.

That's it! Now you should be able to run both the Django server and the React development server and see your tasks being retrieved from the Django server and displayed in the React app.