Part 1 — How to build a File Manager Storage web app with Django Rest Framework and Vue.js with Vuex and Ag-grid integration

Ozgur Yarikkas
Mar 10, 2019 · 9 min read
Image for post
Image for post

Since beginning of this year, I have been attending an online course. We have a platform that enables us to store and share files collaboratively. I wanted to clone it, so this web application idea was born ✍️

I will guide you step by step to create a File Manager storage web application. we will have a tech stack as Django with DRF, vue.js with webpack and vuex and libraries such as ag-grid, bootstrap, axios etc. 🎬

I broke up this tutorial into two parts. Part one focuses on setting up Django with DRF and Vue.js and making configurations and preparing our REST API in backend. Part two goes over frontend and finishing our application with vue.js, vuex and ag-grid. If you want to have a look at part 2 before diving in, follow the link below:

In the first part of this tutorial we are going to:

  • Install and setup Django with Django Rest Framework

Let’s start coding! I suppose that you have Python 3.6+ and Node.js installed.

We start with creating a new environment as following. We are going to use “virtualenv” module which comes with Pythton 3.6

python3 -m venv .env
(Linux and Windows)
virtualenv .env
# Activate your environment
. .env/bin/activate

We are going to use:

Django — Vue.js 2.0 — Webpack

It is good practice to create and requirements.txt file to install our dependencies for Django.

cat > requirements.txt

Press Control + D to save the file or install each library with pip manually.

Enter the following and run requirements.txt to install Django and DRF, also with webpack loader package which we will need to make django to talk to vue.

pip3 install -r requirements.txt

Next, create a Django project

django-admin startproject djvuetut
Image for post
Image for post

Your current file tree should look like this for the moment. You may want to test it and see that it runs in your browser.

cd djvuetut
python runserver # start your server in localhost:8000

Ignore any unapplied migrations warning for the moment and let’s check http://localhost:8000 and make sure you have a running django app!

click control + C to stop the server.

Now, we will continue with Vue.js installation and setup.

~ make sure that you are in the same directory with

enter the commands below to install vue-cli and webpack with simle configuration.

npm install -g vue-cli
vue init webpack-simple
Generate project in current directory? Yes
Project name djvuetut
Project description A Vue.js project
Author talented <>
License MIT
Use sass? No
vue-cli · Generated "djvuetut". To get started:

npm install
npm run dev

as stated:

enter npm install to install dependencies (npm modules) — This may take a while and npm run dev to start the server:

npm install
npm run dev

Default server port for Vue.js is 8080 so you can test that it runs at http://localhost:8080 if it doesn’t load automatically.

Image for post
Image for post

Just a quick introduction on how Vue is working in principal:

→ a vue.js instance is already created in main.js

→ the property el: binds the Vue instance to the HTML element with id=”app” and tell us that it is rendered in App.vue

→ in App.vue we have the Vue.js system to enable us to render data into DOM using double braces syntax.

Configure Django and Vue to work together

Now we need some Vue.js plugins to integrate vue with django. We already installed django-webpack-loader package for django. It requires just a few settings to work. First we need to install the following plugin.

Install the following by using npm

npm install --save-dev webpack-bundle-tracker
npm install --save-dev write-file-webpack-plugin

after installing these packages, it is time to make some configurations. Make the following changes in webpack.config.js

# ./webpack.config.js
var path = require('path');
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker'); // add this
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
// publicPath is deleted here
filename: 'build.js'
plugins: [ // add this new BundleTracker({ // add this filename: './webpack-stats.json' // add this
}) // add this
], // add this module: {
rules: [

in django settings, add the following:

# ./djvuetut/ add 'webpack_loder' to INSTALLED APPSINSTALLED_APPS = [
'webpack_loader', # add this
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR], # update here
'APP_DIRS': True,
'context_processors': [
'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages',
# Add this to the end of settings# settings for django-webpack-loader
STATIC_ROOT = os.path.join(BASE_DIR, 'public')
os.path.join(BASE_DIR, 'dist'),
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
'TIMEOUT': None,
'IGNORE': ['.+\\.hot-update.js', '.+\\.map']

Yes, now we are ready with our configuration. We will need to add our django tags to the main index.html to load the render-bundle from webpack-bundle. final look of index.html will look like below with added tags:

# ./index.html<!DOCTYPE html>
<html lang="en">
<meta charset="utf-8">
{% load render_bundle from webpack_loader %} // add this
<div id="app">
<django></django> // add this
{% render_bundle 'main' %} // add this

We also need to update the in djvuetut folder as follows:

# .djvuetut/urls.pyfrom django.conf.urls import url
from django.contrib import admin
from django.views.generic import TemplateView
urlpatterns = [
path('', TemplateView.as_view(template_name='index.html'), name='Home'),

and we need to add <django> tag as a component to our Vue instance in main.js under /src

# ./src/main.jsimport Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
components: {
'django': App // add this

we should be ready now. Run the latest commands below.

# Compile VueJS App 
npm run build
#collect static files in public folder
python collectstatic
#start django server in localhost
python runserver

Voila! 👏👏👏 when you route to http://localhost:8000 , you should be seeing your view in App.vue. Now you have a fully working vue.js app with a django backend.

Create an API endpoint with Django rest framework

the goal is to create and API endpoint to:

  • upload and download files to the server

let’s start an django app and call it filemanager, so we create our models for our API

django-admin startapp filemanager

we need to add it under INSTALLED_APPS in

we have already installed DRF when we run our requirements.txt but we also need to add it to installed apps to let django know that we are going to use it.

# ./djvuetut/settings.pyINSTALLED_APPS = [
'filemanager' # add this
'rest_framework', # add this

actual file tree should look like this:

Image for post
Image for post

we will also create an admin user to manage our database from admin portal provided by django admin in case we need it. But first we have to migrate any changes before creating a super user:

$ python migrate
$ python createsuperuser
# I think creating a super user is self explanatory. We will use it later.

What we have to do now:

  • Create our model and fields to store file data in database

let’s start with creating a model for our file manager in

# ./filemanager/models.pyfrom django.db import models
from django.utils import timezone
class Data(models.Model):
file_id = models.AutoField(primary_key=True)
file = models.FileField(null=True, max_length=255)
date_created = models.DateTimeField(default =
def __str__(self):
return str(

our model enables us to upload any file with any extension and size. We haven’t setup any validators yet, we will make the fine tuning later. We need to complete a few more configuration to make it work.

# ./djvuetut/settings.pyMEDIA_URL = "/media/"                                 # add this 
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # add this

we also need to configure our and define the new added folder as a static folder.

# ./djvuetut/ 
from django.conf import settings # add this from django.conf.urls.static import static # add this
urlpatterns = [
if settings.DEBUG:
urlpatterns += static( # add this
urlpatterns += static( # add this
settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Django Rest Framework (DRF) Setup

we will define a folder called “media” to keep our files. It will be automatically created in our first upload. now, it is time to create a setup to be able to use DRF.

There are more than one way and I wanted to create the most hassle free setup. It might not be so detailed or if we want to scale our app in the future, we may need to update our code accordingly. To maintain the correct business logic, we are going to create 3 files:


Let me add the required code for each. After that I will give an explanation what they do in general.

Create under ./filemanager and add the following code:

# ./filemanager/serializers.pyfrom rest_framework import serializers
from .models import Data
class DataSerializer(serializers.ModelSerializer): size = serializers.SerializerMethodField()
name = serializers.SerializerMethodField()
filetype = serializers.SerializerMethodField()
since_added = serializers.SerializerMethodField()
class Meta:
model = Data
fields = ('file_id', 'file', 'since_added', 'size', 'name', 'filetype')
def get_size(self, obj):
file_size = ''
if obj.file and hasattr(obj.file, 'size'):
file_size = obj.file.size
return file_size
def get_name(self, obj):
file_name = ''
if obj.file and hasattr(obj.file, 'name'):
file_name =
return file_name
def get_filetype(self, obj):
filename =
return filename.split('.')[-1]
def get_since_added(self, obj):
date_added = obj.date_created
return date_added

Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types.

The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.

We have to use also SerializerMethodField to get the attributes of our file. we can just serialize file_name, file_size and filetype with this way. Get more info about serializers here in original documentation:

create under ./filemanager and add the following code:

# ./filemanager/viewsets.pyfrom rest_framework import viewsets
from .models import Data
from .serializers import DataSerializer
class DataViewSet(viewsets.ModelViewSet):
queryset = Data.objects.all()
serializer_class = DataSerializer

DRF allows you to combine the logic for a set of related views in a single class, called a ViewSet. A ViewSet class is simply a type of class-based View.

We have to provide a queryset and a serializer class that we already created in our

Get more info about viewsets here in original documentation:

create under ./djvuetut and add the following code:

# ./djvuetut/routers.pyfrom rest_framework import routers
from filemanager.viewsets import DataViewSet
router = routers.DefaultRouter()
router.register(r'files', DataViewSet, base_name='data')

With this piece of code, we created a router object and register ‘/files/’ url extension. We want to use it for our API endpoint with also providing our viewSet.

Get more info about routers here in original documentation:

The important point is here that we need to tell django’s that we will use a router to manage our urls with DRF

# ./djvuetut/urls.pyfrom django.contrib import admin
from django.urls import path, include # import "include" here
from .routers import router # add this
...urlpatterns = [
path('', TemplateView.as_view(template_name='index.html'),name='Home'),
path('api/', include(router.urls)), # add this

We are done for now with the DRF settings 🏹 let’s test it out! 😎

Enter the following in your browser and see what is available to us. By the help of DRF, we now have a fully usable rest framework for our model 💪🏻


click on ‘files’ viewset that we defined. Here you can upload a file to test it out. Just choose a file and click on POST. You will notice that a folder with a name “media” will be created in the root directory and the file is uploaded under it.

we will be able to reach the properties of that file through JSON. All we need to do is to parse this JSON query in our Vue views and that’s it. You can upload here more than one file and reach them individually by supplying their ids like that:


In the second part of this series, we will create our front end in vue with bootstrap, integrate ag-grid to showcase our files, create CRUD operations with axios and much more.

click here to read Part 2 of the tutorial! ⚒⚒⚒

Vue.js Developers

Helping web professionals up their skill and knowledge of…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store