Building a Full-Stack Web App with Django and Vue.js

Why Choose Django and Vue.js?

When it comes to building modern web applications, having the right tools is crucial. Django, a Python-based framework, and Vue.js, a popular JavaScript frontend framework, make a powerful combination. Django provides a robust backend, while Vue.js enables you to create interactive and scalable interfaces. With Vue.js, you can take advantage of application reactivity, scalability, and flexibility, as well as component reusability.

Setting Up a Django Project

To get started, create a project folder and navigate to it in your terminal. Then, create a virtual environment using the command:

python -m venv django_rest_api

Activate the virtual environment and install Django using:

pip install django

Initialize and start the Django REST project with:

django-admin startproject django_rest_api_tasks
python manage.py startapp tasks

Creating a Task Model

Define the structure of a task model in tasks/models.py. This will set up a task with title, description, completed, and created_at values.

from django.db import models

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    completed = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

Run the migrations command to initialize the task model to a SQLite database:

python manage.py makemigrations
python manage.py migrate

Adding Django REST Framework

Install Django REST framework using:

pip install djangorestframework

Add rest_framework to the list of installed apps in django_rest_api_tasks/settings.py:

INSTALLED_APPS = [
    #...
    'est_framework',
    #...
]

Create a serializers.py file in the tasks app directory to define the model and fields for the API:

from rest_framework import serializers
from.models import Task

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model = Task
        fields = ['id', 'title', 'description', 'completed', 'created_at']

Setting Up CRUD Operations

In tasks/views.py, handle incoming requests for getting and creating tasks:

from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from.models import Task
from.serializers import TaskSerializer

class TaskList(APIView):
    def get(self, request):
        tasks = Task.objects.all()
        serializer = TaskSerializer(tasks, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = TaskSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Prepare a urls.py file in the tasks app directory to define URLs for fetching and adding tasks, as well as deleting and updating a task with a dynamic ID:

from django.urls import path
from. import views

urlpatterns = [
    path('tasks/', views.TaskList.as_view()),
    path('tasks//', views.TaskDetail.as_view()),
]

Setting Up a CORS API Policy

To enable communication between the Django REST API and the Vue client app, set up a Cross-Origin Resource Sharing (CORS) API policy:

pip install django-cors-headers

Add corsheaders to the list of installed apps in django_rest_api_tasks/settings.py:

INSTALLED_APPS = [
    #...
    'corsheaders',
    #...
]

Setting Up the Vue.js Client App

Create a fresh directory and call it client. Install the Vue CLI using:

npm install -g @vue/cli

Create a new Vue app using:

vue create client

Install Axios using:

npm install axios

Fetched Tasks

Create a Tasks.vue file in the src/components directory:

<template>
  <div>
    <h1>Tasks</h1>
    <ul>
      <li v-for="task in tasks" :key="task.id">
        {{ task.title }}
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      tasks: []
    }
  },
  mounted() {
    axios.get('http://localhost:8000/tasks/')
     .then(response => {
        this.tasks = response.data;
      })
     .catch(error => {
        console.error(error);
      });
  }
}
</script>

Creating a Task

Add a form to create a new task in Tasks.vue:

<template>
  <div>
    <h1>Tasks</h1>
    <form @submit.prevent="submitForm">
      <input type="text" v-model="newTaskTitle" />
      <button type="submit">Create Task</button>
    </form>
    <ul>
      <li v-for="task in tasks" :key="task.id">
        {{ task.title }}
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  data() {
    return {
      tasks: [],
      newTaskTitle: ''
    }
  },
  mounted() {
    axios.get('http://localhost:8000/tasks/')
     .then(response => {
        this.tasks = response.data;
      })
     .catch(error => {
        console.error(error);
      });
  },
  methods: {
    submitForm() {
      axios.post('http://localhost:8000/tasks/', { title: this.newTaskTitle })
       .then(response => {
          this.tasks.push(response.data);
          this.newTaskTitle = '';
        })
       .catch(error => {
          console.error(error);
        });
    }
  }
}
</script>

Updating a Task

Implement the toggleTask method to update a task’s status:

methods: {
  toggleTask(task) {
    axios.patch(`http://localhost:8000/tasks/${task.id}/`, { completed:!task.completed })
     .then(response => {
        task.completed = response.data.completed;
      })
     .catch(error => {
        console.error(error);
      });
  }
}

Deleting a Task

Implement the deleteTask function to delete a task:

methods: {
  deleteTask(task) {
    axios.delete(`http://localhost:8000/tasks/${task.id}/`)
     .then(() => {
        this.tasks = this.tasks.filter(t => t.id!== task.id);
      })
     .catch(error => {
        console.error(error);
      });
  }
}

Leave a Reply