Adding Vue to an existing Django app is super easy, and a great way to enable more complex front-end features. In this post, we’ll see how to do it the easy way.
Why Add Vue?
We’ll get to the code in a minute, but first it’s worth asking — “Why add Vue to your Django project?”
If you just want to add some effects or dynamically render something on the page, vanilla JavaScript is probably a better bet. Just add a script
tag to your page and try to do the manipulations from there.
However, if you have a whole section of the page that needs to share data and re-render often when the user interacts with it, then you probably have a use case for a JavaScript framework, and Vue is a great choice!
Vue allows you to:
- Dynamically render text onto the page (like Django templates, but interactive!)
- Update the CSS, classes, & attributes of various elements on the page
- Define “components,” whole sections of a web page, that render dynamically and are reusable
- Build/restore the state of components based on properties (“props”) that you pass from the server-side or fetch via a REST API
Vue is really cool and fairly easy to learn. It’s similar to learning React, but with a less steep learning curve and easier to set up.
This isn’t a Vue tutorial, so to learn Vue you’ll want to visit the official guide (which is really well done and easy to follow).
Introduction - Vue.js _Vue.js - The Progressive JavaScript Framework_vuejs.org
Let’s see how to add Vue to Django!
Visual learner?
No worries — I made a video of these steps:
Experienced Developers: Just want the code?
Happy to oblige:
bennett39/vue_django _Contribute to bennett39/vue_django development by creating an account on GitHub._github.com
Create a New Django App Before We Start
Before we can add Vue to Django, we need a Django project! I’ll use this project for all the examples that follow.
If you have an existing Django app, you don’t need to copy this. But you should read it just so you know what my app structure looks like.
1.1 Virtual Environment
I use pyenv and pyenv-virtualenv for my environments:
$ pyenv virtualenv vue-app
Looking in links: /var/folders/tz/tjybwp513hd5zvdh166kbwnw0000gn/T/tmp2ler_knw
Requirement already satisfied: setuptools in /Users/bennettgarner/.pyenv/versions/3.8.0/envs/vue-app/lib/python3.8/site-packages (41.2.0)
Requirement already satisfied: pip in /Users/bennettgarner/.pyenv/versions/3.8.0/envs/vue-app/lib/python3.8/site-packages (19.2.3)
$ pyenv local vue-app
1.2 Install Django
Now, we can install Django:
$ pip install django
Next, let’s start a new Django project:
$ django-admin startproject mysite
If we look at the directory now, we’ll see that Django created a new folder for us:
$ ls mysite/
And if we look inside that folder, there’s everything we need to run a Django site:
$ cd mysite/ $ ls manage.py* mysite/
Let’s make sure it works. Test run the Django server:
$ python manage.py runserver
Watching for file changes with StatReloader Performing system checks...
System check identified no issues (0 silenced).
You have 17 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. Run 'python manage.py migrate' to apply them.
July 24, 2020 - 12:14:09 Django version 3.0.8, using settings 'mysite.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Go to http://127.0.0.1:8000 and you should see the Django welcome screen!
1.3 Create the Vue app
We could build our application with the folder structure the way it is right now. However, best practice is to separate your Django project into separate apps when you build something new.
So, let’s create a new app for our Vue application (if you already have an existing project, this will be the app you want to use Vue in).
$ python manage.py startapp vue_app $ ls db.sqlite3 manage.py mysite/ vue_app/
1.4 Register the vue_app app with the mysite project
We need to tell Django to recognize this new app that we just created. The steps we do later won’t work if Django doesn’t know about myapi.
So, we edit mysite/settings.py
:
INSTALLED_APPS = [ 'vue_app.apps.VueAppConfig', ... # Leave all the other INSTALLED_APPS ]
1.5 Migrate the database
We might need the User and session models that come with Django, so let’s have Django add them to the database.
(For those of you thinking, “We didn’t create a database!” You’re right. But Django will create a simple SQLite database for us if we don’t specify differently. And SQLite is awesome!)
So, let’s migrate those initial models:
$ python manage.py migrate
Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying sessions.0001_initial... OK
We’ve got Django up and running! Now, let’s add Vue to our project!
Like what you’ve read so far?
I share my best content with my email list for free.
Join 500 other developers currently in my email series.
The Easy Way to Add Vue: Include Vue in Your Templates
If you just want to use Vue on a single page in your application, the easiest way is to include it inline in the template.
Set Up a Template
In vue_app/
create a templates/
folder. Then, create vue_app/templates/vue_app/
. This type of namespacing is common in Django projects and helps to make sure the templating engine serves the right files.
Now, create test.html
in vue_app/templates/vue_app/
:
Testing, Testing
As you can see, we don’t have Vue in the template at all yet, but we’ll add it soon.
First, let’s define a URL and a view to render the template.
Open vue_app/views.py
(it should already exist):
# vue_app/views.py
from django.shortcuts import render
def test_vue(request): return render(request, 'vue_app/test.html')
Next, we need a URL to point to that view. Go back to the folder where manage.py
is (I called it mysite/
). Then, open mysite/mysite/urls.py
. We’ll just define this URL globally, since it’s the only one in our test app for now.
# mysite/mysite/urls.py
from django.contrib import admin from django.urls import path
from vue_app import views as vue_views # This line is new
urlpatterns = [ path('admin/', admin.site.urls), path('test', vue_views.test_vue), # This line is new ]
If you python manage.py runserver
now and go to http://127.0.0.1:8000/test you should see our test page.
Finally, we can add Vue!
The easiest way to add Vue to our template is a straight import. If you check out the official Vue guide, they have links to a CDN where you can quickly import Vue into your web page:
<!-- development version, includes helpful console warnings --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
OR
<!-- production version, optimized for size and speed --><script src="https://cdn.jsdelivr.net/npm/vue"></script>
Setting up your Django app to use different settings in dev vs. production is outside the scope of this article. There are tons of reasons why you’ll want to have different settings locally, most importantly DEBUG = True
in mysite/settings.py
. It’s worth learning how to do that.
Once you do, you can import the script something like this:
{% if env\_name == 'production' %} {% else %} {% endif %}Testing, Testing
That’s it! You’ve added Vue to your template. Let’s try it out!
Writing your first bit of Vue on Django
Now, we’re ready to write some Vue code!
\[\[ myTitle \]\]
<script type="text/javascript">
let app = new Vue({
el: "#vue-app",
delimiters: \['\[\[', '\]\]'\],
data: {
myTitle: 'Hello Vue!',
},
});
</script>
Couple things to notice here:
- Like all Vue apps, we define a
<div>
where Vue can operate. Think of it like a “window” into our web page where Vue can render things - Since it’s Vue’s window, Vue controls everything inside that
<div>
. If you tried to add script tags or produce side effects inside that window, Vue would strip that out so that it can run reliably. As such, you should make your Vue window as small as possible and compose the page in Vue gradually. - We set custom delimiters on this Vue app. By default Vue uses
{{ }}
for variables in their apps, but that collides with Django templating syntax. So, we changed the delimiters in Vue. - The good news is, once you get used to Vue, you won’t need those delimiters very often. You can often accomplish the same thing without the delimiters:
// Same example as above, but w/ more advanced Vue & no delimiters
Importing from a CDN is by far the easiest way to add Vue to Django, and you’ll actually be able to get pretty far with it before you need to adopt a different strategy…
Cleaning up — static assets
If you continue down this path and try to build a Vue app, you’re going to end up with a lot of huge <script>
tags in your HTML as you define components and logic.
It’s better to collect and serve these scripts as static assets instead of including them directly in the templates themselves. Then, you can also share components across web pages.
Setting up static assets for Django is the subject of entire tutorials, so I’ll leave that out here. Once you have it set up, though, you should be able to keep all your Vue files in a folder like static/src/
.
However, at a certain point you’ll reach a breaking point where those files become pretty big and they can’t easily import one another.
Eventually, you’ll want to make the leap to a build system for Vue.
Adding Webpack to Use Vue CLI & Vue Templates
If you want to use all the features of the Vue CLI and .vue files, then this approach won’t work. You’ll need to compile assets with Webpack.
That involves a bit more configuration, but don’t worry! It’s not too hard to do. I’ve written another post with all the details:
Vue + Django: Using .vue Files and the Vue CLI _Build a full-stack website running on Django_betterprogramming.pub
Vue on Django — We did it!
That wasn’t so hard! Now you can focus on building cool things with Vue on top of an API driven by Django.
Tons of cool modern web apps you use every day use this combination of technologies, so welcome to developing with these two great tools. You’ll be able to build almost anything you can imagine between a Python backend and a JavaScript frontend.
Questions? Comments? Concerns with my approach? Happy to hear them out in the comments below or at vue@bennettgarner.com
About Bennett
I’m a web developer building things with Python and JavaScript.
Want my best content on web development and becoming a better programmer?
I share my favorite advice with my email list — no spam, nothing sales-y, just useful content.