4

I have a Django app for backend, which renders templates with Vue as frontend. My view code in django has the following parts:

# thing/views.py
def index(request):
    template = loader.get_template('thing/index.html')
    return HttpResponse(template.render({}, request))

# thing/urls.py
from django.views.generic import TemplateView

urlpatterns = [
    path('', TemplateView.as_view(template_name='index.html')),
]

# some other files that complete the project are not included

In index.html there is the following code:

<div id="app">
    <p v-if="quotaRemaining > -1">
        Remaining: {{ quotaRemaining }}
    </p>
</div>

<script>
    const app = new Vue({
        el: '#app',
        data: {
            quotaRemaining: 42,
        },
    });
</script>

The only thing that is being rendered when I access this page is:

Remaining:

While I would expect it to be

Remaining: 42

Why is my Vue template not being rendered correctly when served by Django? How do I make it work?

Yury Fedorov
  • 14,508
  • 6
  • 50
  • 66

1 Answers1

13

Django has its own template language, which has a concept of variables. It treats {{ quotaRemaining }} as a Django variable, and processes it even before it gets to the frontend (to Vue). There are at least a couple of solutions.

  1. Surround Vue related code with {% verbatim %} tag:

Stops the template engine from rendering the contents of this block tag. A common use is to allow a JavaScript template layer that collides with Django’s syntax.

    {% verbatim %}
    <p v-if="quotaRemaining > -1">
        Remaining: {{ quotaRemaining }}
    </p>
    {% endverbatim %}
  1. Customize Vue delimiters and use these delimiters in your client code:

     <!-- template code -->
     <p v-if="quotaRemaining > -1">
         Remaining: ${ quotaRemaining }
     </p>
    
     // js code
     const app = new Vue({
         el: '#app',
         delimiters: ['${', '}'],
         data: {
             quotaRemaining: 42,
         },
     });
    
tony19
  • 125,647
  • 18
  • 229
  • 307
Yury Fedorov
  • 14,508
  • 6
  • 50
  • 66