How to Integrate Django and Vue JS Part -2( Creating Simple Todo App)

||
Posted 1 year, 2 months ago
||
Views 222
||
6 min read
1 reaction

This is continous of part 1. I would recommend to check the part 1 if you havent.

Prerequiste,

In this section, we are going to create simple Todo app with Vue JS CDN approach and Django.

Lets create the Todo Model to hold the data.

class Todo(models.Model):
    title = models.CharField(max_length=200)
    completed = models.BooleanField(default=False)

    def __str__(self):
        return self.title

It just hold the title and completed status. This is just for demo purpose. Yes ofcourse real time project will have more complex than this. But idea here is explaining how we can integrate the 2 framework.

Now, lets create the list view in views.py to render the data. As I mentioned in part 1, enable the API is the right approach to handle the data here but for demo we are going to stick with Django regular view method.

def todo_list(request):
    todos = list(Todo.objects.values())
    return JsonResponse(todos, safe=False, status=200)

If you notice the above the view todo_list function, in order to get the Json data we have convereted the queryset into list of values.

Now, lets create the url to hanlde this, as we are going to use front end framework, so I would like to have my url as /api/,

from vuejs.views import  todo_list

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', blog_view),
    path('api/todo/', todo_list),

]

Now its time to handle the Vue Js part to render the data into <div> , lets separate the Vue js part into app.js file. So that we can have clean and neat design to handle it,



var app = new Vue({
    el: '#app',
    delimiters: ['[[', ']]'],
    data: {
        message: 'Hello Techion!',
        todos: "",
        title: '',
        completed: false,
    },
     created() {
        axios
            .get("http://127.0.0.1:8000/api/todo/")
            .then(response => {
                this.response = response.data;
                this.todos = this.response
            })
            .catch(err => console.log(err));
    },

});

Copy & paste the above script in app.js file and link that script in html page like below,

<script type="text/javascript" src="{% static 'js/app.js' %}"></script>

As you see in app.js, we have added the new method called created(), which is one of the Vue Js lifecycle hooks, check here for more details, created() hooks will instantiate when the Vue Js instance call.

Also, if you noticed we have used axios. This is one of the Javascript library to handle the HTTP requests. In order to use that, we need to import that library in our base.html file like below,

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.js"></script>

This will call the api and render the data and store in todos object, We need to display the render object in html like below,

  <div id="app">
        <div class="container">
            <h1 class="center-align">
                Todo App
            </h1>
            
            <br>
            <div class="todo-item" v-for="todo in todos" :key="todo.id">
                <span>
                    <p> [[ todo.title ]]</p>
                  
                </span>
            </div>
        </div>
    </div>

Cool smiley, now we have successfully render the data into our page, now ,lets add few more design to our Html page to handle the addTodo & delete todo options,

Add this below html script ,

<style>
    /* form {
        display: flex;
    } */

    input[type="text"] {
        flex: 10;
        padding: 5px;
    }

    input[type="submit"] {
        flex: 2;
    }

    .todo-item {
        background: #f4f4f4;
        padding: 10px;
        border-bottom: 1px #ccc dotted;
    }

    /* 
    .is-complete {
        text-decoration: line-through;
    } */

    .del {
        background: #ff0000;
        color: #fff;
        border: none;
        /* padding: 5px 9px; */
        border-radius: 50%;
        cursor: pointer;
        float: right;
    }

    .inline {
        display: inline;
    }
</style>

<body>
    <div id="app">
        <div class="container">
            <h1 class="center-align">
                Todo App
            </h1>
            <form @submit.prevent="addTodo">
                <!-- {% csrf_token %} -->
                <input type="text" v-model="title" name="title" placeholder="Add Todo">
                <input type="submit" value="Submit" class="btn">
            </form>
            <br>
            <div class="todo-item" v-for="todo in todos" :key="todo.id">
                <span>
                    <p v-on:click="updTodo(todo.id)" class="inline"> [[ todo.title ]]</p>
                    <button v-on:click="delTodo(todo.id)" class="del inline">x</button>
                </span>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.js"></script>

    <script type="text/javascript" src="{% static 'js/app.js' %}"></script>


</body>

Navigate to http://localhost:8000 to check the output,

If you notice the above html code, we have added few more methods & functions. Let me explain the v-for in Vue Js, Its the template syntax in Vue Js to loop the objects, its like {% for obj in object %} in Django.

Refer the Vue Js Template Syntax here.

Now, lets add all the other related view functions to handle the AddTodo & Delete Todo. In this tutorial, we are going to see these 2 operation, may be you can try the Update operation and post your comments below,


@csrf_exempt
def todo_add(request):
    post_data = request.body.decode('utf-8')
    post_data = json.loads(post_data)
    # print(post_data['body'])
    out = Todo.objects.create(title=post_data['body'])
    todo = list(Todo.objects.filter(id=out.id).values())
    print(todo)
    return JsonResponse(todo, safe=False, status=200)


@csrf_exempt
def todo_delete(request, id):
    print(id)
    obj = Todo.objects.get(id=id)
    obj.delete()
    return JsonResponse({}, safe=False, status=200)

Just for demo purpose, I have used @csrf_exempt method to exclude the csrf_token from Vue Js. Of course, in production you may not require this,



var app = new Vue({
    el: '#app',
    delimiters: ['[[', ']]'],
    data: {
        message: 'Hello Techion!',
        todos: "",
        title: '',
        completed: false,
        

    },
    methods: {
        addTodo() {
         
            axios.post(`http://127.0.0.1:8000/api/todo/add/`, {
                body: this.title

            })
                .then(res => this.todos = [...this.todos, res.data[0]])
                .catch(err => console.log(err));
            this.title = ''
        },
        delTodo(id) {
            axios.delete(`http://127.0.0.1:8000/api/todo/delete/${id}/`)
                .then(res =>
                    this.todos = this.todos.filter(todo => todo.id !== id))
                .catch(err => console.log(err));
        },
       
    },
    created() {
        axios
            .get("http://127.0.0.1:8000/api/todo/")
            .then(response => {
                this.response = response.data;
                this.todos = this.response
            })
            .catch(err => console.log(err));
    },

});

Now, lets copy the above script and replace it in app.js file. And will see what the script does here,

We have introduced the method options here right. Yes this is the one of the key concept in Vue.js. Let say, If i have the submit form in our html page to handle the new Todo request, how Vue will know that angel. That is where these methods will help us,

We can create the method here and use the methods in our HTML to submit , call , click event method to hanlde it.

Add Todo Method

  • We have created the method in app.js file to send the post request using axios and it will send the reuqest to Django todo_add view function and return the data.
  • Returned data will be assigned to todos object/array

Delete Todo Method

  • Likewise, delete method, will execute when delete button clicked on Html page.
  • This will execute the axios delete method and send the request to todo_delete view function

In our html page we need to use the Vue JS Template method to submit the form like below,

<form @submit.prevent="addTodo">
                <!-- {% csrf_token %} -->
                <input type="text" v-model="title" name="title" placeholder="Add Todo">
                <input type="submit" value="Submit" class="btn">
</form>

For delete approach we can use onClick method from Vue Js to handle it,

 <div class="todo-item" v-for="todo in todos" :key="todo.id">
                <span>
                    <p v-on:click="updTodo(todo.id)" class="inline"> [[ todo.title ]]</p>
                    <button v-on:click="delTodo(todo.id)" class="del inline">x</button>
                </span>
            </div>

Final Output looks like below,

You can add new Todo and Delete the todo by clicking the Red X Button :). Hope you enjoy the blog. For video lovers, please check the demo Video below,


1 reaction

Discussion

faisal
Posted 1 year ago

Good,



Joined on April 19, 2020


Latest Videos


Wanna Post Ad?
Reach a large group of audience by posting an ad about your business here. For more details
Drop us a Message