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);
});
}
}