Build an app using Vue and Django
Tags: vue, django
Published: 2023-03-31 03:00:09

by [Anthony Gitau](https://blog.openreplay.com/authors/anthony-gitau)

[Vue.js](https://vuejs.org/guide/quick-start.html) is a popular JavaScript framework for building user interfaces. This guide will teach you how to create a Vue.js app that interacts with data from a Django API. Ensure your computer has the [Node.js](https://nodejs.org/) and [Python 3](https://www.python.org/downloads/) installed.

## Setting up a Django App

First, you must create a [Python virtual environment](https://docs.python.org/3/library/venv.html#:~:text=A%20virtual%20environment%20is%20created,the%20virtual%20environment%20are%20available.) that will be used to set up this project. A virtual environment helps you isolate specific Python environments on a single machine. This allows you to separate dependencies and packages for different projects, which is useful for avoiding conflicts between projects requiring different versions of the same packages.

Navigate to where you want the full-stack Django and Vue app to live and run the following command to install [pipenv](https://pipenv.pypa.io/en/latest/), a tool for creating isolated Python environments, into a single command-line tool. Run the following command to get `pipenv` installed:

```bash
pip install pipenv
```

Create and activate the project's virtual environment using the following command:

```bash
pipenv shell 
```

Install [Django](https://www.djangoproject.com/start/) to your environment:

```bash
pipenv install django
```

Create your Django project using the following command:

```bash
django-admin startproject django_employees_app
```

This will create a simple Django application with the following main file hierarchy:

- `django_employees_app` - the application directory.
- `django_employees_app/django_employees_app` for managing and connecting up the application.
- `manage.py` - for performing various management tasks in a Django project, such as starting the development server, syncing the database, running tests, and creating new Django apps.

Let’s now change the directory to the created `django_employees_app` folder:

```bash
cd django_employees_app
```

Start by creating a new app for managing the API

```bash
python manage.py startapp employees
```

Running this command will create a new app directory named `employees`. It generates the basic files and directories needed for a Django app.

This will be the primary working directory for managing the API. Django treats it as a Python package. Therefore, you need to add it to the `INSTALLED_APPS` list in your project's `settings.py` file to make it available to your project. In your `django_employees_app/django_employees_app/settings.py`, add the created `employees` app to the list of `INSTALLED_APPS` as follows:

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "employees"
]
```

### Installing Django Packages

To create Django API, you need [Django REST framework](https://www.django-rest-framework.org/). It's a powerful and flexible toolkit for building web APIs. It's a third-party package for [Django](https://www.djangoproject.com/start/) that makes it easy to build RESTful APIs using the Django framework.

Thus, install it. You must also add [CORS Headers](https://pypi.org/project/django-cors-headers/) to this API. This will allow the external Vue.js application to communicate with the API and execute any needed operations such as Read, Create, Update, and Delete. To install these packages, run the following command:

```bash
pipenv install djangorestframework django-cors-headers
```

Add the installed packages to the `django_employees_app/django_employees_app/settings.py` file inside the list of `INSTALLED_APPS` as follows:

```python
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "employees",
    'rest_framework',
    'corsheaders',
]
```

In the same file, add `corsheaders` to the `MIDDLEWARE` and `CORS_ORIGIN_ALLOW_ALL = True`. This tells Django to allow Cross-Origin Resource Sharing (CORS) for all origins. Add these changes as follows:

```python
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'corsheaders.middleware.CorsMiddleware',
]

CORS_ORIGIN_ALLOW_ALL = True
```

## Creating the Django Models

A model is a blueprint of your API. A model class represents a table in your database. Each attribute of the class represents a column in the table. In this example, create an `Employee` application. Based on that, create a Model that will define the application's data models.

To define a model, navigate to the `employees/models.py` file. Create a subclass `django.db.models.Model` and define a series of class variables to represent the fields of the model as follows:

```python
from django.db import models

# Create your models here.
class Employee(models.Model):

    fullname = models.CharField(max_length=100, null=True)
    dep = models.TextField(max_length=30, null=True)
    birthdate = models.CharField(max_length=30, null=True)
    salary = models.TextField(max_length=30, null=True)
    created_at = models.DateTimeField(auto_now_add=True , null=True)
    
    class Meta:
        ordering = ['created_at']

    def __str__(self):
        return self.fullname
```

Add the model to the `employees/admin.py` file. This will allow you to test the API in a Django UI.

```python
from django.contrib import admin
from .models import Employee

# Register your models here.
admin.site.register(Employee)
```

Once you have defined the models, run the `makemigrations` and `migrate` commands to create the necessary database tables and apply these changes. Create new database migrations based on the changes in models:

```bash
python manage.py makemigrations
```

Apply them to the database by running the following command:

```bash
python manage.py migrate
```

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/1lxWh2i.png)

A `db.sqlite3` file will be created at the root directory of your project for the SQLite database.

## Creating the Model Serializer

A serializer is a class that converts data from a model instance into JSON format. Serializers facilitate the creation of APIs to allow clients to interact with the data.

Create a model serializer to specify the model fields that should be included in the serialized data. Create an `employees/serializers.py` file and add the `ModelSerializer` as follows:

```python
from rest_framework.serializers import ModelSerializer

from .models import Employee

class EmployeeSerializer(ModelSerializer):
    class Meta:
        model = Employee
        fields = ["id", "fullname", "dep", "birthdate", "salary", "created_at"]
```

## Creating the API Views

Let’s create the requests and responses required for the application API. Add these changes inside the `employees/views.py` file. This will set a Django Rest Framework API and allows you to read, create, retrieve, update, and delete `Employee` objects. Update the `views.py` file as follows:

```python
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .models import Employee
from .serializers import EmployeeSerializer

# Create your views here.
class EmployeeViewSet(ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer
```

To access the view set, create an `employees/urls.py` and define a URL pattern for a Django Rest Framework API as follows:

```python
from django.urls import path

from rest_framework import routers
from .views import EmployeeViewSet

router = routers.DefaultRouter()

router.register('employees', EmployeeViewSet)

urlpatterns = router.urls
```

To use the URL patterns, you need to include them in the project's `urls.py` file. Navigate to `django_employees_app/django_employees_app/urls.py` and update the file and follows:

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

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



<h2>Session Replay for Developers</h2> 
<p><em>
Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data
</em></p>
<img alt="OpenReplay" width="768" height="400" src="https://blog.openreplay.com/assets/overview_Z17Qdyg.png" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em>







## Running the Django API

First, create a `superuser` for the admin:

```bash
python manage.py createsuperuser
```

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/HAoAlFe.png)

Enter a username, email, password, and password (again) as such. To run the API, execute the following command:

```bash
python manage.py runserver
```

This will expose the API on `http://127.0.0.1:8000/` so external servers can access it.

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/Nx0UX4s.png)

To test the API, open `http://127.0.0.1:8000/admin` on the browser and enter your `superuser` details to log in:

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/gwyETtx.png)

Click the **+Add** button under Employees and start interacting with the API.

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/Fiy8sYP.png)

The changes you make here should reflect the SQLite database:

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/KHK1g7s.png)

## Django with Vue

You have the API ready. Let's consume it using a [Vue frontend](https://vuejs.org/guide/quick-start.html). First, create a Vue.js application using the following command:

```bash
npm init vue@latest
```
![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/ZnIjJT9.png)

Change the directory to the newly created application:

```bash
cd Django_Vue_App
```

Run the following command to install the application dependencies:

```bash
npm install
```

To communicate with the API, use the [Axios](https://axios-http.com/docs/intro) library. Axios is a promise-based HTTP client for making HTTP requests to APIs. To install it, run the following command:

```bash
npm install axios
```

To use Axios on a Vue.js application, edit the `src/main.js` file as follows:

```javascript
import { createApp } from 'vue'
import App from './App.vue'
import './assets/main.css'
import axios from 'axios'

const app = createApp(App);
app.config.globalProperties.$http = axios

app.mount('#app')
```

As a requirement, you will require some CSS styling for this guide. [Copy this CSS code](https://github.com/Anthony-Prince/Django-Vue-app/blob/main/Django_Vue_App/src/assets/main.css) into your `src/assets/main.css` file.

### Setting up Vue.js Component

Let's create a component to interact with the employees' API. Navigate to the `src/components` directory and create an `EmployeesList.vue` file. First, create the component scripts that have the `data()` method as follows:

```javascript
<script>
export default {
  data() {
    return {
      employees: [],
      fullname: "",
      dep: "",
      birthdate: "",
      salary: "",
      id: "",
      isEditing: false,
    };
  },
    methods: {
    }
}
</script>

// apply styling to the component

<style scoped>
</style>
```

In this example:

- The `employees` empty array will store the list of employees
- Fullname, dep, birthdate,salary and id will hold the data when creating or editing an employee
- The id property stores the id of the employee that is being edited, or deleted.
- `isEditing` will track whether the component is in editing mode or not and update the component based on the user's actions.
- `methods` object will include methods needed to interact with the data and update the component's state.

## Fetching and Displaying API Data with Vue.js

At this point, ensure the API is running before interacting with it. First, let’s fetch the available employees stored in the API database.

You will require a method to read the data using Axios and the API endpoint. Replace the `methods` object with the following `getEmployee()` function.
Methods:

```javascript
methods: {
    async getEmployee() {
      try {
        await this.$http
          .get(`http://127.0.0.1:8000/api/employees/`)
          .then((response) => {
            this.employees = response.data;
          });
      } catch (error) {
        console.log(error);
      }
    },
},
created() {
    this.getEmployee();
},
```

The main purpose of `getEmployee()` is to send a request to the API and store the result response of `employees` data. To execute `getEmployee()`, create a view using the Vue.js template. This view will read the data response and render it as follows:

```html
<template>
  <div class="content">
    <h1>Employees App</h1>
    <div class="list">
      <ul class="list_content">
        <li v-for="employee in employees" :key="employee.id">
          <h4>{{ employee.fullname }}</h4>
          <h4>{{ employee.dep }}</h4>
          <h4>{{ employee.birthdate }}</h4>
          <h4>{{ employee.salary }}</h4>
        </li>
      </ul>
    </div>
  </div>
</template>
```

To run the component, navigate to `src/App.vue` and make the following changes:

```javascript
<template>
  <div class="app">
    <EmployeesList />
  </div>
</template>

<script>
import EmployeesList from './components/EmployeesList.vue'

export default {
  name: 'App',
  components: {
    EmployeesList,
  }
}
</script>

<style scoped>
</style>
```

Run the following command to test if the application is working correctly:

```bash
npm run dev
```

If everything is correctly set, Vue.js will display the employees you added using Django Admin; try it out.

## Adding and Updating Data using Vue.js

Let's add employee data using Vue.js and save it to the API database. In the `src/components/EmployeesListList.vue` file, create `submitEmployee()` function inside the `methods` object. `submitEmployee()` will create or update an employee, depending on whether the component is in editing mode (`this.isEditing` is true) or creating mode (`this.isEditing` is false) as follows:

```javascript
async submitEmployee() {
    try {
      if (!this.isEditing) {
        await this.$http
          .post(`http://127.0.0.1:8000/api/employees/`, {
            fullname: this.fullname,
            dep: this.dep,
            birthdate: this.birthdate,
            salary: this.salary,
          })
          .then((response) => {
            this.employees.push(response.data);
            this.fullname = "";
            this.dep = "";
            this.birthdate = "";
            this.salary = "";
          });
      } else {
        await this.$http
          .put(`http://127.0.0.1:8000/api/employees/${this.id}/`, {
            fullname: this.fullname,
            dep: this.dep,
            birthdate: this.birthdate,
            salary: this.salary,
          })
          .then((response) => {
            let objIndex = this.employees.findIndex((s) => s.id === this.id);
            let tmp = this.employees;
            tmp[objIndex] = response.data;
            this.employees = tmp;
            this.fullname = "";
            this.dep = "";
            this.birthdate = "";
            this.salary = "";
            this.id = "";
            this.isEditing = false;
            this.getEmployee();
          });
      }
    } catch (error) {
      console.log(error);
    }
},
```

Here you are executing the `POST` and `PUT` requests at the same time. If the component is not in the editing mode (`isEditing` is false), execute the `POST` request to create a new employee. Pass in the employee properties as the data to be sent in the request. If the request is successful, it will add the response data to the `employees` array and clear component adding form.

If the component is in editing mode (`isEditing` is true), execute the `PUT` request to update an existing employee. Here, pass in the `id` of the employee to update, along with the updated employee values. If the `PUT` request is successful, reset `isEditing` to false.

To track if `isEditing = true` based on the employee being updated, let's create another method. Inside the `methods` object, create an `editEmployee()` function as follows:

```javascript
async editEmployee(employee) {
  try {
    this.isEditing = true;
    this.fullname = employee.fullname;
    this.dep = employee.dep;
    this.birthdate = employee.birthdate;
    this.salary = employee.salary;
    this.id = employee.id;
  } catch (error) {
    console.log(error);
  }
},
```

Next, create a template to render the above `methods`. Replace the existing `template` as follows:

```html
<template>
  <div class="content">
    <h1>Employees App</h1>

    <div class="add_form">
      <form v-on:submit.prevent="submitEmployee">
        <input
          type="text"
          class="form-control"
          placeholder="Full Nmae"
          v-model="fullname"
        />
        <input
          type="text"
          class="form-control"
          placeholder="Birth Date"
          v-model="dep"
        />
        <input
          type="text"
          class="form-control"
          placeholder="Department"
          v-model="birthdate"
        />
        <input
          type="text"
          class="form-control"
          placeholder="Salary"
          v-model="salary"
        />
        <button type="submit" class="btn btn-primary">
          {{ isEditing ? "Edit Employee" : "Add Employee" }}
        </button>
      </form>
    </div>

    <div class="list">
      <ul class="list_content">
        <li v-for="employee in employees" :key="employee.id">
          <h4>{{ employee.fullname }}</h4>
          <h4>{{ employee.dep }}</h4>
          <h4>{{ employee.birthdate }}</h4>
          <h4>{{ employee.salary }}</h4>
          <div class="list_buttons">
            <button @click="editEmployee(employee)">Edit</button>
            <button @click="deleteEmployee(employee)">Delete</button>
          </div>
        </li>
      </ul>
    </div>

  </div>
</template>
```

Your application should be updated as follows:

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/lpGGaVj.png)

Use the form to add new data. Also, Click **Edit** to update the selected employee. Note: this will set `isEditing`  to true and update the state as follows:

![-](https://blog.openreplay.com/images/build-an-app-using-vue-and-django/images/oVc2ILj.png)

## Deleting Data using Vue.js

Likewise, let's add a new method to delete as exiting done as follows:

```javascript
async deleteEmployee(employee) {
  if (!confirm("Are you sure?")) {
    return;
  }
  await this.$http.delete(`http://127.0.0.1:8000/api/employees/${employee.id}/`);
  await this.getEmployee();
},
```

Clicking the **Delete** button should remove the selected employee. These changes should reflect in the database as well.

## Conclusion

Django provides intuitive solutions that are easy to learn and use when creating API. On the other end, Vue.js is a lightweight framework for building user interfaces. This guide has helped you understand how to build full-stack apps using Vue.js and Django.



[![newsletter](https://blog.openreplay.com/newsletter_Z1P0UIP.png)](https://newsletter.openreplay.com/)