One place for hosting & domains

      Build

      Build A Progressive Web Application With Nuxt.js

      Introduction

      Ever since its announcement by Google, the adoption of progressive web apps has skyrocketed as many traditional web apps have been and are being converted to progressive web apps. In this tutorial, I’ll be showing you how to build a progressive web app with Nuxt.js. For the purpose of the demonstration, we’ll be building a news app.

      This tutorial assumes a basic knowledge of progressive web app.

      Nuxt.js is a framework for building server-side rendered Vue.js applications.

      We’ll start by creating a new Nuxt.js app. For this, we’ll make use of the Vue CLI, so you need to first install the Vue CLI in case you don’t have it installed already:

      1. npm install -g vue-cli

      Then we can create a Nuxt.js app:

      1. vue init nuxt/starter pwa-news

      Next, we need to install the dependencies:

      1. cd pwa-news
      2. npm install

      We can now launch our app:

      1. npm run dev

      The app should be running on http://localhost:3000.

      With our app up and running, let’s now install the necessary Nuxt.js modules that we’ll be needing for our news app:

      1. npm install @nuxtjs/axios @nuxtjs/bulma @nuxtjs/dotenv

      Let’s quickly go over each of the module:

      • @nuxtjs/axios: Secure and easy Axios integration with Nuxt.js.
      • @nuxtjs/bulma: This module leverages the lovely Bulma CSS framework.
      • @nuxtjs/dotenv: This module loads your .env file into your context options.

      Next, let’s make Nuxt.js use these modules. We’ll do that by adding them in the modules section of the nuxt.config.js file:

      nuxt.config.js

      modules: [
          '@nuxtjs/axios',
          '@nuxtjs/dotenv',
          '@nuxtjs/bulma'
      ]
      

      Our news app will be built on News API. So we need to get our API key.

      Click on the Get API key button then follow along with the registration to get your API key.

      With our API key in place, let’s start building our news app. First, let’s update the layouts/default.vue file as below:

      layouts/default.vue

      <template>
          <div>
              <section class="hero has-text-centered is-primary">
                  <div class="hero-body">
                      <div class="container">
                          <h1 class="title">PWA News</h1>
                          <h2 class="subtitle">All the headlines making the wavy!</h2>
                      </div>
                  </div>
              </section>
              <nuxt/>
          </div>
      </template>
      
      <style>
          html {
              font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
          }
      </style>
      

      We are simply making use of the Bulma classes.

      Next, let’s update the pages/index.vue file as well:

      pages/index.vue

      <template>
          <section class="section">
              <div class="container">
                  <div class="columns is-multiline">
                      <div
                          class="column is-one-quarter"
                          v-for="(article, index) in articles"
                          :key="index"
                      >
                          <a :href="article.url" target="_blank">
                              <div class="card">
                                  <div class="card-image">
                                      <figure class="image is-3by2">
                                          <img :src="article.urlToImage" :alt="article.title">
                                      </figure>
                                  </div>
                                  <div class="card-content">
                                      <div class="content">{{ article.title }}</div>
                                  </div>
                              </div>
                          </a>
                      </div>
                  </div>
              </div>
          </section>
      </template>
      
      <script>
          export default {
              async asyncData({ app }) {
                  const { articles } = await app.$axios.$get(
                      `https://newsapi.org/v2/top-headlines?sources=cnn&apiKey=${
                          process.env.API_KEY
                      }`
                  );
      
                  return { articles };
              },
          };
      </script>
      

      In the template section, we loop through the news headlines and display each headline in a card (using Bulma classes) with a link to view the news directly on the source. On the script section, because we’ll be fetching the news headlines and rendering them on the server-side, so we make use of the asyncData method. Then making use of the Nuxt.js axios module installed earlier, we make a GET request to the New API endpoint to fetch news headlines, passing along the source we want to fetch from and our API key. Lastly, we return a articles object containing the fetched news headlines. With this, we can access the articles object as we would access any other component data.

      You will notice we are getting our API key from an environment variable, which we are yet to create. Let’s do that now. Create a new .env file directly in the project root directory:

      1. touch .env

      Then add the code below into it:

      .env

      API_KEY=YOUR_API_KEY
      

      Now, if we test our app, we should get something similar to the image below:

      So far our news is feature complete. But our goal for this tutorial is to build a progressive web app. So, let’s add the progressive web app awesomeness to our news app. To do this, we make use of a Nuxt.js module called Nuxt PWA.

      Using Nuxt PWA you can supercharge your current or next Nuxt project with a heavily tested, updated, and stable PWA solution and zero-config!

      Nuxt PWA module is a collection of smaller modules that are designed to magically work out of the box together. These modules includes:

      • Workbox – Registers a service worker for offline caching.
      • Manifest – Automatically generate manifest.json file.
      • Meta – Automatically adds SEO friendly meta data with manifest integration.
      • Icon – Automatically generates app icons with different sizes.
      • Onesignal – Free background push notifications using onesignal.

      For the purpose of this tutorial, we’ll be making use of only the first 4 modules, as we won’t be covering push notifications.

      The lovely thing about Nuxt PWA is that it works straight out of the box with zero configuration. So let’s install and set it up:

      1. npm install @nuxtjs/pwa

      Next, we add the module to the nuxt.config.js file:

      nuxt.config.js

      modules: [
          ...,
          '@nuxtjs/pwa'
      ]
      

      Lastly, we need an icon for our news app. Though this is optional, it will give our app that native feel once our app is added to the home screen of our user’s devices. For this tutorial, we’ll use the icon from the Nuxt.js HackerNews clone. So download and place it in the static directory.

      Note: It is recommended that the icon be a square png and >= 512x512px and named icon.png.

      That’s all we need to do to make use of the Nuxt PWA module. Because by default, the workbox module is only enabled on production builds, we need to build our news app for production:

      1. npm run build

      Once the build is done, we can start our app with:

      1. npm start

      Then we can view the app at http://localhost:3000.

      We get pretty much the same thing from earlier. To see indeed that our app is now a progressive web app, try setting our app to offline (which simulates no internet connection) under the Application tab on Chrome DevTools and refresh the page.

      The app should still be running fine as our app is been cached for offline view.

      Also, we can use the Lighthouse extension to test if our app meets the standards for a progressive web app. Under the Audits tab (you might have to download the Lighthouse extension if you can’t find this tab) of Chrome DevTools, click on the perform an audit… button and click on Run audit:

      This will start performing some checks on our app. Once it’s complete, we should get a screen as below:

      We are more focused on the Progressive Web App section. As you can see, our app got an 82/100, which is a great score. If we narrow the result down, you’ll see that our app only failed 2 audits, which is understandable since our app is still running on localhost.

      So in this tutorial, we looked at how we can build a progressive web app with Nuxt.js. With this tutorial, you should be able to convert an existing Nuxt.js application into a progressive web app. We also looked at how we can test a progressive web app using the Lighthouse extension. I hope you found this tutorial helpful.

      Build a To-Do App with Vue.js 2

      Introduction

      Vue is a simple and minimal progressive JavaScript framework that can be used to build powerful web applications incrementally.

      Vue is a lightweight alternative to other JavaScript frameworks like AngularJS. With an intermediate understanding of HTML, CSS, and JS, you should be ready to get up and running with Vue.

      In this article, we will be building a to-do application with Vue while highlighting the bundle of awesomeness that it has to offer.

      Let’s get started!

      We’ll need the Vue CLI to get started. The CLI provides a means of rapidly scaffolding Single Page Applications and in no time you will have an app running with hot-reload, lint-on-save, and production-ready builds.

      Vue CLI offers a zero-configuration development tool for jumpstarting your Vue apps and component.

      A lot of the decisions you have to make regarding how your app scales in the future are taken care of. The Vue CLI comes with an array of templates that provide a self-sufficient, out-of-the-box ready to use package. The currently available templates are:

      • webpack – A full-featured Webpack + Vue-loader setup with hot reload, linting, testing, and CSS extraction.
      • webpack-simple – A simple Webpack + Vue-loader setup for quick prototyping.
      • browserify – A full-featured Browserify + vueify setup with hot-reload, linting & unit testing.
      • browserify-simple – A simple Browserify + vueify setup for quick prototyping.
      • simple – The simplest possible Vue setup in a single HTML file

      Simply put, the Vue CLI is the fastest way to get your apps up and running.

      1. npm install --global vue-cli

      In this tutorial, we will be focusing on the use of single file components instead of instances. We’ll also touch on how to use parent and child components and data exchange between them. Vue’s learning curve is especially gentle when you use single-file components. Additionally, they allow you to place everything regarding a component in one place. When you begin working on large applications, the ability to write reusable components will be a lifesaver.

      Next, we’ll set up our Vue app with the CLI.

      1. vue init webpack todo-app

      You will be prompted to enter a project name, description, author, and Vue build. We will not install Vue-router for our app. You will also be required to enable linting and testing options or the app.
      You can follow my example below.

      Once we have initialized our app, we will need to install the required dependencies.

      1. cd todo-app
      2. npm install

      To serve the app, run:

      1. npm run dev

      This will immediately open your browser and direct you to http://localhost:8080. The page will look as follows.

      To style our application we will use Semantic. Semantic is a development framework that helps create beautiful, responsive layouts using human-friendly HTML. We will also use Sweetalert to prompt users to confirm actions. Sweetalert is a library that provides beautiful alternatives to the default JavaScript alert. Add the minified JavaScript and CSS scripts and links to your index.html file found at the root of your folder structure.

      
      <head>
        <meta charset="utf-8">
        <title>todo-app</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.7/semantic.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.7/semantic.min.js"></script>
        <link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.3/sweetalert.min.js"></script>
      </head>
      

      Every Vue app, needs to have a top-level component that serves as the framework for the entire application. For our application, we will have a main component, and nested within shall be a TodoList component. Within this, there will be Todo sub-components.

      Let’s dive into building our application. First, we’ll start with the main top-level component. The Vue CLI already generates a main component that can be found in src/App.vue. We will build out the other necessary components.

      The Vue CLI creates a component Hello during setup that can be found in src/components/Hello.vue. We will create our own component called TodoList.vue and won’t be needing this anymore.

      Inside of the new TodoList.vue file, write the following.

      <template>
        <div>
        <ul>
          <li> Todo A </li>
          <li> Todo B </li>
          <li> Todo C </li>
        </ul>
        </div>
      </template>
      
      <script type="text/javascript">
        export default {
        };
      </script>
      
      <style>
      </style>
      

      A component file consists of three parts; template, component class, and styles sections.

      The template area is the visual part of a component. Behaviour, events, and data storage for the template are handled by the class. The style section serves to further improve the appearance of the template.

      To utilize the component we just created, we need to import it into our main component. Inside of src/App.vue make the following changes just above the script section and below the template closing tag.

      
      import TodoList from './components/TodoList'
      
      import Hello from './components/Hello'
      

      We will also need to reference the TodoList component in the components property and delete the previous reference to Hello component. After the changes, our script should look like this.

      <script>
      import TodoList from './components/TodoList';
      
      export default {
        components: {
          
          TodoList,
        },
      };
      </script>
      

      To render the component, we invoke it like an HTML element. Component words are separated with dashes like below instead of camel case.

      <template>
        <div>
          
          
          <todo-list></todo-list>
        </div>
      </template>
      

      When we have saved our changes our rudimentary app should look like this.

      We will need to supply data to the main component that will be used to display the list of todos. Our todos will have three properties; The title, project, and done (to indicate if the todo is complete or not). Components provide data to their respective templates using a data function. This function returns an object with the properties intended for the template. Let’s add some data to our component.

      export default {
        name: 'app',
        components: {
          TodoList,
        },
        
        data() {
          return {
            todos: [{
              title: 'Todo A',
              project: 'Project A',
              done: false,
            }, {
              title: 'Todo B',
              project: 'Project B',
              done: true,
            }, {
              title: 'Todo C',
              project: 'Project C',
              done: false,
            }, {
              title: 'Todo D',
              project: 'Project D',
              done: false,
            }],
          };
        },
      };
      

      We will need to pass data from the main component to the TodoList component. For this, we will use the v-bind directive. The directive takes an argument which is indicated by a colon after the directive name. Our argument will be todos which tells the v-bind directive to bind the element’s todos attribute to the value of the expression todos.

      <todo-list v-bind:todos="todos"></todo-list>
      

      The todos will now be available in the TodoList component as todos. We will have to modify our TodoList component to access this data. The TodoList component has to declare the properties it will accept when using it. We do this by adding a property to the component class.

      export default {
          props: ['todos'],
      }
      

      Inside our TodoList template let’s loop over the list of todos and also show the number of completed and uncompleted tasks. To render a list of items, we use the v-for directive. The syntax for doing this is represented as v-for="item in items" where items are the array with our data and item is a representation of the array element being iterated on.

      <template>
        <div>
          
          <p>Completed Tasks: {{todos.filter(todo => {return todo.done === true}).length}}</p>
          <p>Pending Tasks: {{todos.filter(todo => {return todo.done === false}).length}}</p>
          <div class='ui centered card' v-for="todo in todos">
            <div class='content'>
              <div class='header'>
                {{ todo.title }}
              </div>
              <div class='meta'>
                {{ todo.project }}
              </div>
              <div class='extra content'>
                <span class='right floated edit icon'>
                  <i class='edit icon'></i>
                </span>
              </div>
            </div>
            <div class='ui bottom attached green basic button' v-show="todo.done">
              Completed
            </div>
            <div class='ui bottom attached red basic button' v-show="!todo.done">
              Complete
            </div>
        </div>
      </template>
      
      <script type="text/javascript">
        export default {
          props: ['todos'],
        };
      </script>
      

      Let’s extract the todo template into it’s own component for cleaner code. Create a new component file Todo.vue in src/components and transfer the todo template. Our file should now look like this:

      <template>
        <div class='ui centered card'>
          <div class='content'>
              <div class='header'>
                  {{ todo.title }}
              </div>
              <div class='meta'>
                  {{ todo.project }}
              </div>
              <div class='extra content'>
                  <span class='right floated edit icon'>
                  <i class='edit icon'></i>
                </span>
              </div>
          </div>
          <div class='ui bottom attached green basic button' v-show="todo.done">
              Completed
          </div>
          <div class='ui bottom attached red basic button' v-show="!todo.done">
              Complete
          </div>
      </div>
      </template>
      
      <script type="text/javascript">
        export default {
          props: ['todo'],
        };
      </script>
      

      In the TodoList component refactor the code to render the Todo component. We will also need to change the way our todos are passed to the Todo component. We can use the v-for attribute on any components we create just like we would in any other element. The syntax will be like this: <my-component v-for="item in items" :key="item.id"></my-component>.

      Note that from 2.2.0 and above, a key is required when using v-for with components.

      An important thing to note is that this does not automatically pass the data to the component since components have their own isolated scopes. To pass the data, we have to use props.

      <my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index">
      </my-component>
      

      Our refactored TodoList component template:

      <template>
        <div>
          <p>Completed Tasks: {{todos.filter(todo => {return todo.done === true}).length}}</p>
          <p>Pending Tasks: {{todos.filter(todo => {return todo.done === false}).length}}</p>
          
          <todo v-for="todo in todos" v-bind:todo="todo"></todo>
        </div>
      </template>
      
      <script type = "text/javascript" >
      
      import Todo from './Todo';
      
      export default {
        props: ['todos'],
        components: {
          Todo,
        },
      };
      </script>
      

      Let’s add a property to the Todo component class called isEditing. This will be used to determine whether the Todo is in edit mode or not. We will have an event handler on the Edit span in the template. This will trigger the showForm method when it gets clicked. This will set the isEditing property to true. Before we take a look at that, we will add a form and set conditionals to show the todo or the edit form depending on whether isEditing property is true or false. Our template should now look like this.

      <template>
        <div class='ui centered card'>
          
          <div class="content" v-show="!isEditing">
            <div class='header'>
                {{ todo.title }}
            </div>
            <div class='meta'>
                {{ todo.project }}
            </div>
            <div class='extra content'>
                <span class='right floated edit icon' v-on:click="showForm">
                <i class='edit icon'></i>
              </span>
            </div>
          </div>
          
          <div class="content" v-show="isEditing">
            <div class='ui form'>
              <div class='field'>
                <label>Title</label>
                <input type='text' v-model="todo.title" />
              </div>
              <div class='field'>
                <label>Project</label>
                <input type='text' v-model="todo.project" />
              </div>
              <div class='ui two button attached buttons'>
                <button class='ui basic blue button' v-on:click="hideForm">
                  Close X
                </button>
              </div>
            </div>
          </div>
          <div class='ui bottom attached green basic button' v-show="!isEditing &&todo.done" disabled>
              Completed
          </div>
          <div class='ui bottom attached red basic button' v-show="!isEditing && !todo.done">
              Pending
          </div>
        </div>
      </template>
      

      In addition to the showForm method we will need to add a hideForm method to close the form when the cancel button is clicked. Let’s see what our script now looks like.

      <script>
      export default {
        props: ['todo'],
        data() {
          return {
            isEditing: false,
          };
        },
        methods: {
          showForm() {
            this.isEditing = true;
          },
          hideForm() {
            this.isEditing = false;
          },
        },
      };
      </script>
      

      Since we have bound the form values to the todo values, editing the values will immediately edit the todo. Once done, we’ll press the close button to see the updated todo.

      Let’s begin by adding an icon to delete a Todo just below the edit icon.

      <template>
        <span class='right floated edit icon' v-on:click="showForm">
          <i class='edit icon'></i>
        </span>
        /* add the trash icon in below the edit icon in the template */
        <span class='right floated trash icon' v-on:click="deleteTodo(todo)">
          <i class='trash icon'></i>
        </span>
      </template>
      

      Next, we’ll add a method to the component class to handle the icon click. This method will emit an event delete-todo to the parent TodoList Component and pass the current Todo to delete. We will add an event listener to the delete icon.

      <span class='right floated trash icon' v-on:click="deleteTodo(todo)">
      
      
      methods: {
          deleteTodo(todo) {
            this.$emit('delete-todo', todo);
          },
        },
      

      The parent component (TodoList) will need an event handler to handle the delete. Let’s define it.

      
      methods: {
          deleteTodo(todo) {
            const todoIndex = this.todos.indexOf(todo);
            this.todos.splice(todoIndex, 1);
          },
        },
      

      The deleteTodo method will be passed to the Todo component as follows.

      
      <todo v-on:delete-todo="deleteTodo" v-for="todo in todos" v-bind:todo="todo"></todo>\
      

      Once we click on the delete icon, an event will be emitted and propagated to the parent component which will then delete it.

      To create a new todo, we’ll start by creating a new component CreateTodo in src/components. This will display a button with a plus sign that will turn into a form when clicked. It should look something like this.

      <template>
        <div class='ui basic content center aligned segment'>
          <button class='ui basic button icon' v-on:click="openForm" v-show="!isCreating">
            <i class='plus icon'></i>
          </button>
          <div class='ui centered card' v-show="isCreating">
            <div class='content'>
              <div class='ui form'>
                <div class='field'>
                  <label>Title</label>
                  <input v-model="titleText" type='text' ref='title' defaultValue="" />
                </div>
                <div class='field'>
                  <label>Project</label>
                  <input type='text' ref='project' defaultValue="" />
                </div>
                <div class='ui two button attached buttons'>
                  <button class='ui basic blue button' v-on:click="sendForm()">
                    Create
                  </button>
                  <button class='ui basic red button' v-on:click="closeForm">
                    Cancel
                  </button>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>
      
      <script>
      export default {
        data() {
          return {
            titleText: '',
            projectText: '',
            isCreating: false,
          };
        },
        methods: {
          openForm() {
            this.isCreating = true;
          },
          closeForm() {
            this.isCreating = false;
          },
          sendForm() {
            if (this.titleText.length > 0 && this.projectText.length > 0) {
              const title = this.titleText;
              const project = this.projectText;
              this.$emit('create-todo', {
                title,
                project,
                done: false,
              });
              this.newTodoText = '';
            }
            this.isCreating = false;
          },
        },
      };
      </script>
      

      After creating the new component, we import it and add it to the components property in the component class.

      
        components: {
          TodoList,
          CreateTodo,
        },
      

      We’ll also add a method for creating new todos.

      
        methods: {
          addTodo(title) {
            this.todos.push({
              title,
              done: false,
            });
          },
        },
      

      The CreateTodo component will be invoked in the App.vue template as follows:

      <create-todo v-on:add-todo="addTodo">
      

      Finally, we’ll add a method completeTodo to the Todo component that emits an event complete-todo to the parent component when the pending button is clicked and sets the done status of the todo to true.

      
      methods: {
            completeTodo(todo) {
              this.$emit('complete-todo', todo);
            },
      }
      

      An event handler will be added to the TodoList component to process the event.

      methods: {
          completeTodo(todo) {
            const todoIndex = this.todos.indexOf(todo);
            this.todos[todoIndex].done = true;
          },
        },
      

      To pass the TodoList method to the Todo component we will add it to the Todo component invocation.

      <todo v-on:delete-todo="deleteTodo" v-on:complete-todo="completeTodo" v-for="todo in todos" :todo.sync="todo"></todo>
      

      We have learned how to initialize a Vue app using the Vue CLI. In addition, we learned about component structure, adding data to components, event listeners, and event handlers. We saw how to create a todo, edit it and delete it. There is a lot more to learn. We used static data in our main component. The next step is to retrieve the data from a server and update it accordingly. We are now prepared to create an interactive Vue application. Try something else on your own and see how it goes. Cheers!

      Build a REST API with Django – A Test Driven Approach: Part 1

      Introduction

      Code without tests is broken as designed.
      — Jacob Kaplan-Moss

      In software development, testing is paramount. So why should I do it, you ask?

      • Tests have a short feedback loop, enabling you and your team to learn faster and adjust
      • Less time is spent debugging, allowing you to spend more time writing code
      • Tests act as documentation for your code!
      • They improve code quality while reducing bugs
      • After refactoring code, your tests will tell you whether the change has broken previously working code

      The best way to do code testing is by using Test-Driven Development (TDD).

      This is how it works:

      • Write a test. – The test will flesh out some functionality in your app
      • Then, run the test – The test should fail since there’s no code to make it pass.
      • Write the code – To make the test pass
      • Run the test – If it passes, you are confident that the code you’ve written meets the test requirements
      • Refactor code – Remove duplication, prune large objects and make the code more readable. Re-run the tests every time you refactor the code
      • Repeat – That’s it!

      Being a fan of best practices, we are going to use TDD to create a bucketlist API. The API will have CRUD (Create, Read, Update, Delete) and authentication capabilities. Let’s get to it then!

      The aim of this article is to help you learn awesome stuff while creating new things. We’ll be creating a bucket list API. If you haven’t heard about the term bucket list, it is a list of all the goals you want to achieve, dreams you want to fulfill, and life experiences you desire to experience before you die (or hit the bucket). This API should therefore help us to create and manage our bucketlists.

      To be on the same page, the API should have the ability to:

      • Create a Bucketlist
      • Retrieve a Bucketlist
      • Update it
      • And, Delete one’s bucketlist

      Other complementary functionalities that will come later will be:

      • Authentication of API Users
      • Searching Bucketlists
      • Adding bucketlist items into a bucketlist
      • Pagination

      New to Python, Django?

      If you haven’t done any Django, Check out Building your first Django application. It’s an excellent resource for beginners.

      Now that we know about a bucketlist, here’s a bit about the tools we’ll use to create its app.

      Django Rest Framework (or simply DRF) is a powerful module for building web APIs. It’s very easy to build model-backed APIs that have authentication policies and are browsable.

      Why DRF?

      • Authentication – From basic and session-based authentication to token-based and Oauth2 capabilities, DRF is king.
      • Serialization – It supports both ORM and Non-ORM data sources and seamlessly integrates with your database.
      • Great Documentation – If you get stuck somewhere, you can refer to its vast online documentation and great community support
      • Heroku, Mozilla, Red Hat, and Eventbrite are among the top companies using DRF in their APIs.

      Requirements

      For DRF to work, you must have:

      Create and cd into your project folder. You can call the folder anything you like.

      1. mkdir projects && $_

      Then, create a virtual environment to isolate our code from the rest of the system.

      1. virtualenv -p /usr/local/bin/python3 venv

      The -p switch tells virtualenv the path to the python version you want to use. Ensure that you put the correct python installation path after the -p switch. venv is your environment. Even though you can name your environment anything, it’s considered best practice to simply name it venv or env.

      Activate your virtual environment by doing this:

      1. source venv/bin/activate

      You will see a prompt with the environment name (i.e., (venv)). It means the environment is now active. Now we’re ready to install our requirements inside our environment.

      Inside the projects folder, install Django using pip

      1. pip install Django

      If you lack pip in your system, simply do:

      1. sudo easy_install pip

      Since we need to keep track of our requirements, we’ll create a requirements.txt file.

      1. touch requirements.txt

      And add the installed requirements into the text file using pip freeze

      1. pip freeze > requirements.txt

      Then finally, create a Django project.

      1. django-admin startproject djangorest

      We should now have a folder with the name djangorest created. Feel free to give it any other name.
      The folder structure should look like this:

      djangorest
      ├─djangorest
      │   ├── __init__.py
      │   ├── settings.py
      │   ├── urls.py
      │   └── wsgi.py
      └── manage.py
      

      Integrating DRF

      Using pip, install DRF

      1. pip install djangorestframework

      For our app to use DRF, we’ll have to add rest_framework into our settings.py. Let’s go right ahead and do that.

      
      ...
      
      
      
      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles', 
          'rest_framework', 
      ]
      

      In Django, we can create multiple apps that integrate to form one application. An app in Django is simply a python package with a bunch of files including the __init__.py file.

      First, cd into the djangorest directory on your terminal. We do this so that we can access the manage.py file. Then create the app as follows:

      1. python3 manage.py startapp api

      The startapp command creates a new app. Our app is called api. It will hold our API logic. So far, you should have a folder named api alongside the djangorest app. To integrate our api app with the djangorest main app, we’ll have to add it to our djangorest settings.py. Let’s go right ahead and do that.

      ...
      
      
      
      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          'rest_framework',
          'api', 
      ]
      

      First, we test!

      We’d want to create the models first. But we have no tests written. We’ll therefore write some tests in the tests.py folder of our API app.

      
      
      from django.test import TestCase
      from .models import Bucketlist
      
      
      class ModelTestCase(TestCase):
          """This class defines the test suite for the bucketlist model."""
      
          def setUp(self):
              """Define the test client and other test variables."""
              self.bucketlist_name = "Write world class code"
              self.bucketlist = Bucketlist(name=self.bucketlist_name)
      
          def test_model_can_create_a_bucketlist(self):
              """Test the bucketlist model can create a bucketlist."""
              old_count = Bucketlist.objects.count()
              self.bucketlist.save()
              new_count = Bucketlist.objects.count()
              self.assertNotEqual(old_count, new_count)
      

      The code above imports the test case from django.test. The test case has a single test that tests whether the model can create a bucketlist with a name.

      Then, we define our models

      We need to create a blank model class. This is done in our models.py

      
      
      from django.db import models
      
      
      class Bucketlist(models.Model):
        pass
      

      Running the test is super easy with Django. We’ll use the test command as follows:

      1. python3 manage.py test

      You should see a bunch of errors all over the screen. Don’t worry about it. It’s because we haven’t written our model fields and updated our database yet. Django uses SQlite as its default database so we’ll use it for now. Also, we don’t have to write a single SQL statement when creating the models. Django handles all that for us. In the models.py we’ll define fields that will represent the table fields in our database.

      
      
      from django.db import models
      
      
      class Bucketlist(models.Model):
        """This class represents the bucketlist model."""
          name = models.CharField(max_length=255, blank=False, unique=True)
          date_created = models.DateTimeField(auto_now_add=True)
          date_modified = models.DateTimeField(auto_now=True)
      
          def __str__(self):
              """Return a human readable representation of the model instance."""
              return "{}".format(self.name)
      

      We migrate!

      Migrations are Django’s way of propagating changes you make to your models (like adding a field, deleting a model, etc.) into your database schema.

      Now that we have a rich model in place, we need to tell the database to create the relevant schema.

      In your console, run this:

      1. python3 manage.py makemigrations

      This creates a new migration based on the changes we’ve made to our model.

      Then, apply the migrations to your DB by doing this:

      1. python3 manage.py migrate

      When you run the tests, you should see something like this:

      The tests have passed! This means that we can proceed to write the serializers for our app

      Serializers serialize and deserialize data. So what’s all this about, you ask?

      Serializing is changing the data from complex querysets from the DB to a form of data we can understand, like JSON or XML. Deserializing is reverting this process after validating the data we want to save to the DB.

      Model Serializers are awesome!

      The ModelSerializer class lets you automatically create a Serializer class with fields that correspond to the Model fields. This reduces our lines of code significantly.

      Create a file called serializers.py inside the API directory.

      Let’s write some code in it:

      
      
      from rest_framework import serializers
      from .models import Bucketlist
      
      
      class BucketlistSerializer(serializers.ModelSerializer):
          """Serializer to map the Model instance into JSON format."""
      
          class Meta:
              """Meta class to map serializer's fields with the model fields."""
              model = Bucketlist
              fields = ('id', 'name', 'date_created', 'date_modified')
              read_only_fields = ('date_created', 'date_modified')
      

      We’ll first write the view’s tests. Writing tests seems daunting at first. However, it’s easy to know what to test when you know what to implement.

      In our situation, we want to create views that will handle the following:

      • Create a bucketlist – Handle POST request
      • Read a bucketlist(s) – Handle GET request
      • Update a bucketlist – Handle PUT request
      • Delete a bucketlist – Handle DELETE request

      Based on the above functionality, we know what to test. We’ll use them as a guide.

      Let’s take the first case. If we want to test whether the API will create a bucketlist successfully, we’ll write the following code in tests.py:

      
      
      
      from rest_framework.test import APIClient
      from rest_framework import status
      from django.core.urlresolvers import reverse
      
      
      class ViewTestCase(TestCase):
          """Test suite for the api views."""
      
          def setUp(self):
              """Define the test client and other test variables."""
              self.client = APIClient()
              self.bucketlist_data = {'name': 'Go to Ibiza'}
              self.response = self.client.post(
                  reverse('create'),
                  self.bucketlist_data,
                  format="json")
      
          def test_api_can_create_a_bucketlist(self):
              """Test the api has bucket creation capability."""
              self.assertEqual(self.response.status_code, status.HTTP_201_CREATED)
      

      This test fails when we run it. This is ok. It happens so because we haven’t implemented the views and URLs for handling the POST request.

      Let’s go ahead and implement them! On views.py, write the following code:

      
      
      from rest_framework import generics
      from .serializers import BucketlistSerializer
      from .models import Bucketlist
      
      
      class CreateView(generics.ListCreateAPIView):
          """This class defines the create behavior of our rest api."""
          queryset = Bucketlist.objects.all()
          serializer_class = BucketlistSerializer
      
          def perform_create(self, serializer):
              """Save the post data when creating a new bucketlist."""
              serializer.save()
      

      The ListCreateAPIView is a generic view that provides GET (list all) and POST method handlers

      Notice we specified the queryset and serializer_class attributes. We also declare a perform_create method that aids in saving a new bucketlist once posted.

      For it to be complete, we’ll specify URLs as endpoints for consuming our API. Think of URLs as an interface to the outside world. If someone wants to interact with our web API, they’ll have to use our URL.

      Create a urls.py file on the API directory. This is where we define our URL patterns.

      
      
      from django.conf.urls import url, include
      from rest_framework.urlpatterns import format_suffix_patterns
      from .views import CreateView
      
      urlpatterns = {
          url(r'^bucketlists/$', CreateView.as_view(), name="create"),
      }
      
      urlpatterns = format_suffix_patterns(urlpatterns)
      

      The format_suffix_pattern allows us to specify the data format (raw JSON or even HTML) when we use the URLs. It appends the format to be used for every URL in the pattern.

      Finally, we add a URL to the main app’s urls.py file so that it points to our API app. We will have to include the api.urls we just declared above into the main app urlpatterns.

      Go to the djangorest folder and add the following to the urls.py:

      
      
      
      from django.conf.urls import url, include
      
      urlpatterns = [
          url(r'^admin/', admin.site.urls),
          url(r'^', include('api.urls')) 
      ]
      

      We’ll run our server the Django way with the runserver command:

      1. python3 manage.py runserver

      You should see this output on your console

      That means everything is running smoothly.

      Enter the server-specified URL (http://127.0.0.1:8000/bucketlists) in your browser. And viola – It works!

      Go ahead and write a bucketlist and click the post button to confirm whether our API works.

      You should see something like this:

      Writing the tests

      We’ll write three more tests to cater for GET, PUT and DELETE requests. We’ll wrap them as follows:

          
      
          def test_api_can_get_a_bucketlist(self):
              """Test the api can get a given bucketlist."""
              bucketlist = Bucketlist.objects.get()
              response = self.client.get(
                  reverse('details',
                  kwargs={'pk': bucketlist.id}), format="json")
      
              self.assertEqual(response.status_code, status.HTTP_200_OK)
              self.assertContains(response, bucketlist)
      
          def test_api_can_update_bucketlist(self):
              """Test the api can update a given bucketlist."""
              change_bucketlist = {'name': 'Something new'}
              res = self.client.put(
                  reverse('details', kwargs={'pk': bucketlist.id}),
                  change_bucketlist, format='json'
              )
              self.assertEqual(res.status_code, status.HTTP_200_OK)
      
          def test_api_can_delete_bucketlist(self):
              """Test the api can delete a bucketlist."""
              bucketlist = Bucketlist.objects.get()
              response = self.client.delete(
                  reverse('details', kwargs={'pk': bucketlist.id}),
                  format='json',
                  follow=True)
      
              self.assertEquals(response.status_code, status.HTTP_204_NO_CONTENT)
      

      If we run these tests, they should fail. Let’s fix that.

      It’s time we complete the API with a PUT and DELETE method handlers.

      We’ll define a view class for this. On the views.py file, add the following code:

      
      
      class DetailsView(generics.RetrieveUpdateDestroyAPIView):
          """This class handles the http GET, PUT and DELETE requests."""
      
          queryset = Bucketlist.objects.all()
          serializer_class = BucketlistSerializer
      

      RetrieveUpdateDestroyAPIView is a generic view that provides GET (one), PUT, PATCH, and DELETE method handlers.

      Finally, we create this new URL to be associated with our DetailsView.

      
      
      from .views import DetailsView
      
      url(r'^bucketlists/(?P<pk>[0-9]+)/$',
              DetailsView.as_view(), name="details"),
      

      Enter the specified URL (http://127.0.0.1:8000/bucketlists/1/) in your browser. And voila! – It works! You can now edit the existing bucketlist.

      Phew! Congratulations for making it to the end of this article – You are awesome!

      In Part 2 of the Series, we’ll delve into adding users, integrating authorization and authentication, documenting the API, and adding more refined tests.

      Want to dig deeper? Feel free to read more of DRF’s Official Documentation.

      And if you’re new to Django, I find Django For Beginners excellent.