Is Golang taking place in web development? What are the pros compared to Rails, Django or Node?

The Features you need to know when using Javascript in 2020

The Features you need to know when using Javascript in 2020

A peek into the future of the JavaScript language, take a look at the exciting stage and features you need to know when using Javascript in 2020

Javascript reach has increased from a web browser to all places of programming.

  1. Node.js — Used for CLI and Server.

  2. Electron — Used for cross-platform desktop Apps.

  3. React native — Used for cross-platform mobile Apps.

  4. IoT — Low-cost IoT devices, now support javascript.

Recent updates to v8 engine have increased the performance a lot. The javascript parsing is 2x faster, promise on an avg is 11x faster on node version ≥11 from node version 8. The memory consumption as decreased -20%. So there is an improvement in performance and usability.

In this article, we will see some of the presents and purposed features that you can test in chrome browser (version ≥76) or Node.js(version ≥11) CLI.

Private Class field👇

Until ES6, we were not able to declare private properties directly. Yes there were ways like underscore convention (_propertyName), closures, symbols, or WeakMaps.

But now private class fields use a hash # prefix. Let’s learn it by an example.

class Test {
  a = 1;          // .a is public
  #b = 2;         // .#b is private
  static #c = 3;  // .#c is private and static
  incB() {
    this.#b++;
  }
}
const testInstance = new Test();
// runs OK
testInstance.incB();
// error - private property cannot be modified outside class
testInstance.#b = 0;

*Note: There’s no way to define the private function as of now, although a TC39 stage 3: draft proposal suggests using a hash # prefix on names.

You may also like: Keeping your JavaScript code clean forever and scalable.

String.matchAll()👇

If I have a string, with a global regular expression which has many capturing groups, I often want to iterate through all groups. Currently, my options are the following:

  1. String.prototype.match() with /g — If we use .match() with a regular expression whose flag /g is set, you get all full matches for it in an Array.

  2. String.prototype.split() — If we use a split string and regular expression to specify the separator and if it contains at least one capture group then .split() returns an Array in which the substrings are interleaved.

The issues with the above approach are that they only work if /g is set on regular expression and the property .lastIndex of a regular expression is changed each time a match happens. This makes using the same regular expression at multiple locations risky.

The matchAll() help resolve all above. Let’s check out the definition and usage

Given a string and a regular expression, .matchAll() returns all results matching a string against a regular expression, including capturing groups.

let regexp = /t(e)(st(\d?))/g;
let str = 'test1test2';
let array = [...str.matchAll(regexp)];
console.log(array[0]);
// expected output: Array ["test1", "e", "st1", "1"]

Note: .matchAll() returns an iterator, not a true restartable iterable. That is, once the result is exhausted, you need to call the method again and create a new iterator.

Numeric Separators👇

If you have struggled to read a long sequence of number, this is where your search end.

Numeric Separators allow the human eye to parse quickly, especially when there are lots of repeating digits:

1000000000000 -> 1_000_000_000_000
1019436871.42 -> 1_019_436_871.42

Now it’s easier to tell that the first number is a trillion, and the second number is in the order of 1 billion.

It also works on other bases, for example:

const fileSystemPermission = 0b111_111_000;
const bytes = 0b1111_10101011_11110000_00001101;
const words = 0xFAB_F00D;

You can also use the separator in the fractions and exponents:

const massOfElectronInKg = 9.109_383_56e-31;
const trillionInShortScale = 1e1_2;

Note: Parsing the _ separated integer can be tricky as Number('123_456') gives NAN whereas parseInt('123_456') gives 123

BigInt’s👇

BigInts are a new numeric primitive in JavaScript that can represent integers with precision larger than 2⁵³–1. With BigInts, you can safely store and operate on large integers even beyond the safe integer limit for Numbers .

BigInts correctly perform integer arithmetic without overflowing. Let’s understand by an example:-

const max = Number.MAX_SAFE_INTEGER;
// 9007199254740991
max+1;
// 9007199254740992
max+2;
// 9007199254740991

We can see that max + 1 produces the same result as max + 2 .

Any calculation on integers outside the safe integer range (i.e. from Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER) potentially loses precision. For this reason, we can only rely on numeric integer values within the safe range.

Therefore, BigInts came to existence, BigInts can be created by adding the n suffix to any integer literal. For example, 123 becomes 123n or the global BigInt(number) function can be used to convert a Number into a BigInts.

Let’s revisit the above example with BigInts

BigInt(Number.MAX_SAFE_INTEGER) + 2n;
// 9007199254740993n
typeof 123n
// "bigint2"

Note: Numeric separators are especially helpful with BigInts, for eg: const massOfEarthInKg = 6_000_000_000_000_000_000_000_000n;

BigInts support the most common operators. Binary +, -, *, and ** all work as expected. / and % work, and round towards zero as needed.

(7 + 6 - 5) * 4 ** 3 / 2 % 3;
// → 1
(7n + 6n - 5n) * 4n ** 3n / 2n % 3n;
// → 1n

Note: One gotcha is that it’s not allowed to mix operations between BigInts and Numbers

Locale String with BigInt👇

The toLocaleString() method returns a string with a language-sensitive representation of the BigInt.

let bigint = 123456789123456789n;

// German uses period for thousands
console.log(bigint.toLocaleString('de-DE'));
// → 123.456.789.123.456.789

// Arabic in most Arabic speaking countries uses Eastern Arabic digits
console.log(bigint.toLocaleString('ar-EG'));
// → ١٢٣٬٤٥٦٬٧٨٩٬١٢٣٬٤٥٦٬٧٨٩

// India uses thousands/lakh/crore separators
console.log(bigint.toLocaleString('en-IN'));
// → 1,23,45,67,89,12,34,56,789

// the nu extension key requests a numbering system, e.g. Chinese decimal
console.log(bigint.toLocaleString('zh-Hans-CN-u-nu-hanidec'));
// → 一二三,四五六,七八九,一二三,四五六,七八九

// when requesting a language that may not be supported, such as
// Balinese, include a fallback language, in this case Indonesian
console.log(bigint.toLocaleString(['ban', 'id']));
// → 123.456.789.123.456.789
GlobalThis Keyword👇

JavaScript’s variable scopes are nested and form a tree whose root is the global scope and the value of the this keyword is a reference to the object that “owns” the currently executing code or the function where its looked at.

Usually to figure out the global this we use a function like

const getGlobalThis = () => {

  // in webworker or service worker
  if (typeof self !== 'undefined') return self;

  // in browser 
  if (typeof window !== 'undefined') return window;

  // in Node.js
  if (typeof global !== 'undefined') return global;

  // Standalone javascript shell
  if (typeof this !== 'undefined') return this;

  throw new Error('Unable to locate global object');
};
const theGlobalThis = getGlobalThis();

The above function does not cover all cases when we need global this value.

  1. In the case of use strict the value of this is undefined.

  2. When we form a bundle in the javascript it usually wraps under some code that might differ the global this.

  3. In Standalone javascript engine shell environment, the above code will not work.

To solve the above problem globalThis keyword is introduced which returns global this object in any environment at any time.

Note: The global object is now considered a mistake that JavaScript can’t get rid of, due to backward compatibility. It affects performance negatively and is generally confusing.

Promise.allSettled()👇

If you are wondering what’s promise is in javascript then check out this — JavaScript Promises: an Introduction.

A little gist, a promise is JavaScript’s way of promising you that work will be done (or might fail if the work could not be completed).

The new method returns a promise that resolves after all of the given promises have settled i.e either resolved or rejected, with an array of objects that each describe the outcome of each promise.

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];
Promise.allSettled(promises).
  then((results) => results.forEach((result) => console.log(result.status)));
// expected output:
// "fulfilled"
// "rejected"

This is different from the Promise.all as it rejects as soon as a promise within the iterable object rejected.

Below is the comparison of current supported promises method

![](https://i.imgur.com/NpAaXb2.png)

Promise.all, Promise.allSettled, Promise.race

Dynamic Import 👇
![](https://i.imgur.com/vovyPRX.png)

Static vs Dynamic Import

This one is crazy before we dive into it, let’s first see what static import is.

Static import only accepts a string literal as the module specifier and introduces bindings into the local scope via a pre-runtime “linking” process.

The static import syntax can only be used at the top-level of the file.

import * as module from './utils.mjs';

Static import enables important use cases such as static analysis, bundling tools, and tree-shaking.

But what about

  • import a module on-demand (or conditionally)

  • compute the module specifier at runtime

  • import a module from within a regular script (as opposed to a module)

This was not possible until dynamic importsimport(moduleSpecifier) returns a promise for the module namespace object of the requested module, which is created after fetching, instantiating, and evaluating all of the module’s dependencies, as well as the module itself.

<script type="module">
  (async () => {
    const moduleSpecifier = './utils.mjs';
    const module = await import(moduleSpecifier)
    module.default();
    // → logs 'Hi from the default export!'
    module.doStuff();
    // → logs 'Doing stuff…'
  })();
</script>

Note: Use static imports for initial paint dependencies, especially for above-the-fold content. In other cases, consider loading dependencies on-demand with dynamic import().

You may also like: Top 8 Trends and Tools Front-End JavaScript for 2020.

Stable Sorting — (Consistent and reliable result now)👇

By Stable in the algorithmic sense means: does it preserve the order or otherwise “equal” items?

Let’s understand by an example

const people = [
  {name: 'Gary', age: 20},
  {name: 'Ann', age: 20},
  {name: 'Bob', age: 17},
  {name: 'Sue', age: 21},
  {name: 'Sam', age: 17},
];

// Sort people by name
people.sort( (p1, p2) => {
  if (p1.name < p2.name) return -1;
  if (p1.name > p2.name) return 1;
  return 0;
});

console.log(people.map(p => p.name));
// ['Ann', 'Bob', 'Gary', 'Sam', 'Sue']
// Re-sort people by age

people.sort( (p1, p2) => {
  if (p1.age < p2.age) return -1;
  if (p1.age > p2.age) return 1;
  return 0;
});

console.log(people.map(p => p.name));
// We're expecting people sorted by age, then by name within age group:
// ['Bob', 'Sam', 'Ann', 'Gary', 'Sue']
// But we might get any of these instead, depending on the browser:
// ['Sam', 'Bob', 'Ann', 'Gary', 'Sue']
// ['Bob', 'Sam', 'Gary', 'Ann', 'Sue']
// ['Sam', 'Bob', 'Gary', 'Ann', 'Sue']

If you’re getting one of the last three results, then you’re probably using Google Chrome, or maybe one of an assortment of browsers that do not implement Array.sort() as a “stable” algorithm.

This is because different JS engines (across different browsers) taking different routes to implement sort, Also, some javascript engine use stable sort for short array but for long array uses unstable sort.

This lead to inconsistent in sort stability behavior and a lot of confusion. This is why in the development environment everything related to sort seems to work but in the production environment, we start to see something else due to the varying size of array the sort was tested on.

Note: There are 3rd party libraries, I heartily recommend Lodash, which has stable sort

But this has been resolved now, we have a stable sort on most of the browsers. The syntax remains the same.

Since this article has a lot to digest and try-test features, we will continue with the more new feature in the next one.

Thank you for reading!

The Ultimate VueJs and Django CRUD Tutorial

The Ultimate VueJs and Django CRUD Tutorial

The Ultimate VueJs and Django CRUD Tutorial - In this tutorial, We show you how to build an API with Django REST Framework and a SPA with Vue.js.

Originally published by  Junior Gantin at dunebook.com

As a developer, CRUD (Create-Read-Update-Delete) is one of the basic operations to know. In this tutorial, I’ll show you how to build an API with Django REST Framework and a SPA with Vue.js. I am going to show you step by step from scratch.

Take a look at the CRUD app we will build:


CRUD API with Django REST Framework

Django REST framework is a powerful and flexible toolkit for building Web APIs. Open your favorite command-line interface and make sure to install Pipenv. Pipenv is one of the best tools to manage Python project dependencies. alternatively, you can use CodeMix IDE for fast and smooth Vue and Python app development.

mkdir subscription-api
cd subscription-api
pipenv install --three
pipenv shell
pipenv install django
pipenv install django-rest-framework

BashCopy

Right now, we’ve installed Django and Django REST Framework. Let’s create a Django project and a Django app:

./manage.py startproject subscription-api .
./manage.py startapp subscriptions

So make sure to add subscriptions and restframework to our list of INSTALLEDAPPS in the settings.py file.

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

Our database model will contain Subscription model only. Let’s create 6 fields:

# subscriptions/models.py
from django.db import models

class Subscription(models.Model):
    name = models.CharField(max_length=255)
    description = models.TextField()
    currency = models.CharField(max_length=255)
    amount = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def str(self):
        return self.name

Now let’s update our database by first creating a new migration file and then applying it.

./manage.py makemigrations
./manage.py migrate

Create a serializer to convert our data into JSON format:

# subscriptions/serializers.py
from rest_framework import serializers
from .models import Subscription

class SubscriptionSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subscription
        fields = ('name', 'description', 'currency',
            'amount', 'created_at', 'updated_at'
        )

Django REST Framework provides class-based generic API views. Update the views.py file:

# subscriptions/views.py
from .models import Subscription
from .serializers import SubscriptionSerializer
from rest_framework import generics

class SubscriptionList(generics.ListCreateAPIView):
    queryset = Subscription.objects.all()
    serializer_class = SubscriptionSerializer

class SubscriptionDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Subscription.objects.all()
    serializer_class = SubscriptionSerializer

Let’s add our API endpoints.

# subscription_api/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('api', include('subscriptions.urls')),
    path('admin/', admin.site.urls),
]


# subscriptions/urls.py
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from subscriptions import views

urlpatterns = [
    path('subscriptions/', views.SubscriptionList.as_view()),
    path('subscriptions/<int:pk>/', views.SubscriptionDetail.as_view()),
]

Start the server.

./manage.py runserver

Your browsable API is ready.

 

Let’s add Cross-Origin Resource Sharing (CORS) headers to responses with django-cors-headers:

pipenv install django-cors-headers

And then add it to your installed apps:

# subscription_api/settings.py
INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

You will also need to add a middleware class to listen in on responses:

# subscription_api/settings.py
MIDDLEWARE = [
    ...
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    ...
]

Just allow all origins to make cross-site HTTP requests:

# subscription_api/settings.py
CORS_ORIGIN_ALLOW_ALL = True
Vue.js CRUD REST API Consumption

Make sure you have the latest version of vue-cli installed.

vue create subscription-app
cd subscription-app
yarn add axios bootstrap bootstrap-vue vee-validate

We just create a new Vue.js project and installed:

  • axios: a great HTTP client library;
  • bootstrap and bootstrap-vue: a library to quickly integrate Bootstrap 4 components with Vue.js;
  • vue-validate: validate HTML inputs and Vue components the easy way.

Inside src/components folder, create the following Vue components:

  • Index.vue
  • Create.vue
  • Edit.vue

Make sure to import bootstrap and vee-validate in your main.js:

// src/main.js
...
import BootstrapVue from "bootstrap-vue";
import VeeValidate from "vee-validate";

import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap-vue/dist/bootstrap-vue.css";

Vue.use(BootstrapVue);
Vue.use(VeeValidate);
...

Now, we need to define our routes.

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: "/",
      redirect: '/index'
    },
    {
      path: "/create",
      name: "create",
      component: () => import("./components/Create.vue")
    },
    {
      path: "/edit/:id",
      name: "edit",
      component: () => import("./components/Edit.vue")
    },
    {
      path: "/index",
      name: "index",
      component: () => import("./components/Index.vue")
    },
  ]
});

Each route should map to a component we created. We created a redirection to redirect from /to /index.

The next step should be to define a router view in App.vue file.

Index.vue

So the first file called will be Index.vue. This component will display all subscriptions.

Let’s explain this deeper. We need to get all subscriptions from our API. Create a property called susbscriptions:

...
    data() {
        return {
            subscriptions: []
        }
    },
...

Create a method which gets all subscriptions from server with axios:

...
all: function () {
        axios.get('http://127.0.0.1:8000/api/subscriptions/')
            .then( response => {
                this.subscriptions = response.data
            });
    }
...

Call method when Index component is created:

...
created() {
    this.all();
},
...

The Index template part is just a Bootstrap card component with a for-loop.

We create a delete button into the template.

<button
    class="btn btn-danger btn-sm ml-1"
    v-on:click="deleteSubscription(subscription)">
    Delete
</button>

deleteSubscription is called when the button is clicked.

deleteSubscription: function(subscr) {
    if (confirm('Delete ' + subscr.name)) {
        axios.delete(http://127.0.0.1:8000/api/subscriptions/${subscr.id})
            .then( response => {
                this.all();
            });
    }
},

This method will call your API after you confirm the deletion.

Create.vue

This file will create and store a subscription. We’ll use vee-validate which is a template based validation library.

We create a property called subscription and a boolean called submitted:

...
subscription: {
    name: '',
    currency: '',
    amount: '',
    description: '',
},
submitted: false
...

All we need is to add the v-validate directive to the input we wish to validate. Like below:

<input
    type="text"
    class="form-control"
    id="name"
    v-model="subscription.name"
    v-validate="'required'"
    name="name"
    placeholder="Enter name">

The CSS class we bind is just a Bootstrap 4 HTML5 form validation hint wich display invalid-feedback block.

<input
...
    :class="{
        'is-invalid':
            errors.has('subscription.name')
        && submitted}">

So let’s store our subscription.

create: function (e) {
    this.$validator.validate().then(result => {
        this.submitted = true;
        if (!result) {
            return;
        }
        axios
            .post('http://127.0.0.1:8000/api/subscriptions/',
                this.subscription
            )
            .then(response => {
                this.$router.push('/');
            })
    });
}

We make a HTTP request and return to / path when everything works.

Edit.vue

When the Edit.vue component is loaded, then we fetch the subscription data from the database and then display it inside the same form we used in Create.vue.

I hope this is helpful to you. You can check out the subscription-app repo.

Originally published by  Junior Gantin at dunebook.com

==================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Nuxt.js - Vue.js on Steroids

☞ Vue JS 2 - The Complete Guide (incl. Vue Router & Vuex)

☞ Python and Django Full Stack Web Developer Bootcamp

☞ Django 2.1 & Python | The Ultimate Web Development Bootcamp

☞ Master Vuejs from scratch (incl Vuex, Vue Router)

☞ Vue JS 2.0 - Mastering Web Apps

☞ Vue.js Essentials - 3 Course Bundle

☞ MEVP Stack Vue JS 2 Course: MySQL + Express.js + Vue.js +PHP

☞ Python eCommerce | Build a Django eCommerce Web Application

☞ Python Django Dev To Deployment

☞ The Complete JavaScript Course 2019: Build Real Projects!

☞ JavaScript: Understanding the Weird Parts

☞ The Modern JavaScript Bootcamp (2019)

How to Use a SQL Like and Regex Search in MongoDB and Node.JS

How to Use a SQL Like and Regex Search in MongoDB and Node.JS

In this article we will know how to use Regex to search in MongoDB like the SQL Like Statement

In this article we will know how to use Regex to search in MongoDB like the SQL Like Statement

To select the documents from a collection, you can use the db.collection.find() method. To select all documents in the collection, pass an empty document as the query filter document to the method.

In the shell, copy and paste the following to return all documents in the members collection.

db.members.find({})

To format the results, append the .pretty() to the find operation:

db.members.find({}).pretty()

Searching for Word Using Regex

Now that we are using .find() to query our collection, we can actually modify our syntax ever so slightly and begin searching for matches based on a word or phrase that may be a partial match within a given field, similar to the LIKE operator for SQL engines.

The trick is to utilize regular expressions (or regex for short), which is basically a text string that defines a search pattern. There are a number of regex engines that are written in slightly different syntax, but the fundamentals are all basically the same, and in this case, MongoDB uses the Perl Regex (PCRE) engine.

At the most basic level, a regex expression is a string (series of characters) enclosed on both sides by a single slash (/).

For example, if we want to use regex to perform the same query as above and find out how many members serve Neha, we can replace our string "Neha" with /Neha/ instead:

db.members.find( { name: /Neha/ } )

But imagine we want to find the number of restaurants where borough starts with the first three characters "Neha". We’d modify our regex very slightly, like so:

db.members.find( { name: /^Neha/ } )

The caret character (^) specifies the location in our string which should be the beginning, so if we had a document where those three letters were in the middle of the field, we wouldn’t get a match.

This informs the regex engine that we want to the search to be case insensitive, matching regardless of upper or lowercase. We also added the special i flag following our regex closing slash (/):

db.members.find( { name: /Neha/i } )

Using variable regex with MongoDB in Node.JS

var search ='Neha';

db.members.find(name: new RegExp(search)) //For substring search, case sensitive. 

db.members.find(name: new RegExp('^' + search + '$')) //For exact search, case sensitive

db.members.find(name: new RegExp(search, ‘i')) //For substring search, case insensitive

db.members.find(name: new RegExp('^' +search + '$', 'i')); //For exact search, case insensitive

Happy Coding!

Please like and share so I have the motivation to continue sharing!

What is the difference between PM2 Cluster vs Fork Mode in Node.JS

What is the difference between PM2 Cluster vs Fork Mode in Node.JS

97 The main difference between fork_mode and cluster_mode is that it orders pm2 to use either the child_process.fork api or the cluster api.

The main difference between fork_mode and cluster_mode is that it orders pm2 to use either the child_process.fork api or the cluster api.

Fork mode

Take the fork mode as a basic process spawning. This allows to change the exec_interpreter, so that you can run a php or a python server with pm2. Yes, the exec_interpreter is the "command" used to start the child process. By default, pm2 will use node so that pm2 start server.js will do something like:

require('child_process').spawn('node', ['server.js'])

This mode is very useful because it enables a lot of possibilities. For example, you could launch multiple servers on pre-established ports which will then be load-balanced by HAProxy or Nginx.

Cluster mode

The cluster will only work with node as it's exec_interpreter because it will access to the nodejs cluster module (eg: isMaster, fork methods etc.). This is great for zero-configuration process management because the process will automatically be forked in multiple instances.

For example pm2 start -i 4 server.js will launch 4 instances of server.js and let the cluster module handle load balancing.

Creating a Weather App in Django Using Python Requests

Creating a Weather App in Django Using Python Requests

In this tutorial, I'll create a weather app in Django that gets the current weathers for multiple cities. To do this, I'll use Python Requests to call the Open Weather Map API.

In this tutorial, I'll create a weather app in Django that gets the current weathers for multiple cities. To do this, I'll use Python Requests to call the Open Weather Map API.

To get the current weather data, we'll use the Open Weather Map API.

Table of Contents

  • Installation
  • The Admin Dashboard
  • Creating the App
  • Adding the Template and View
  • Using the Weather API
  • Displaying the Data in the Template
  • Creating the Form
  • Conclusion

Even though the app is simple, we'll work with a database and create a form, so the concepts used here are applicable to more complicated projects.

The code in this article was written with Python 3 and Django 2.0, so to follow this tutorial, you should be somewhat familiar with both. If you'd like an introduction to both, check out our article called Build Your First Python and Django Application. That article uses Django 1.X, but you'll see the only difference is in how URLs are defined.

Here's what our app is going to look like when we're done.

Creating a Weather App in Django Using Python Requests

You can see a live demo of the app on Python Anywhere.

All the code for this article is on GitHub.

If you'd like to see a video of me building this app, check out this YouTube video:

Installation

Installing Django is like installing any other Python library: you can start a virtual environment and run pip to install Django, or you can do what I do and create a project directory, run pipenv and then activate the pipenv shell. Either method works, but for this article I'll be using pipenv.

pipenv install django

This will install the latest version of Django for you. At the time of writing this article, Django is on version 2.0.4.

Once you have Django installed, create and navigate to a directory for this project if you haven't already. Once there, you can run the startproject command that Django gives you to generate the project.

django-admin startproject the_weather

Django should have created a few new files in your directory.

Let's try starting up our development server. To do that, navigate to the new directory and use manage.py to run the runserver command in your terminal:

cd the_weather
python manage.py runserver

If you look at your terminal, you should see the URL for your app. By default it should be 127.0.0.1:8000.

Creating a Weather App in Django Using Python Requests

Open up your browser and go to that URL.

Creating a Weather App in Django

If you see that, you know you've set up Django correctly. You definitely should see it because we haven't even tried modifying the code yet.

The Admin Dashboard

Next we want to take a look at the admin dashboard Django gives us. To do that, first we have to migrate our database, which means Django will create the pre-defined tables that are needed for the default apps. To do this, you simply run the migrate command. Stop the server by using CTRL+C and then run:

python manage.py migrate

By running that command, Django has created a SQLite database for you, the default database in the settings, and it has added several tables to that database. You'll know if the database was created if you see a new db.sqlite3 file in your project directory.

One of the tables Django gives us is a user table, which will be used to store any users in our app. The app we're building doesn't need any users, but having an admin user will allow us to access the admin dashboard.

To create an admin user, we'll run the createsuperuser command.

python manage.py createsuperuser

Follow the instructions by giving a username, email address, and a password for your admin user. Once you've done that, you'll need to start the server again and navigate to the admin dashboard.

python manage.py runserver

Then go to 127.0.0.1:8000/admin.

The reason why we can go to this page is because because admin is set up in our urls.py (the reason why we can see the congratulations page is because Django gives you that until you add your own URLs).

If you login with the username and password you just created, you should see this page.

Creating a Weather App in Django Using Python Requests

Groups and users represent two models Django gives us access to. Models are just code representations of tables in a database. Even though Django created more tables, there's no need to access the rest of them directly, so no models were created.

If you click on 'user' you should see more detail about the user table, and you should see the user you created. I recommend clicking different links in the dashboard to see what's there. Just be careful not to delete your user, otherwise you'll have to run createsuperuser again.

Let's leave the admin dashboard for now and go to the code. We need to create an app inside of our project for our weather app.

Creating the App

In Django, you can separate functionality in your project by using apps. I think app is a confusing name because we usually refer to an app as being the entire project, but in the case of Django, app refers to a specific piece of functionality in your project. For example, if you look at the settings.py file, you'll see the INSTALLED_APPS list.

The first of the installed apps, django.contrib.admin is what we just used. It handles all the admin functionality and nothing else. Another app in our project by default are things like auth, which allowed us to log into our admin dashboard.

In our case, we need to create a new app to handle everything related to showing the weather. To create that app, stop the server with CTRL+C and run:

python manage.py startapp weather

By running startapp, Django has added a new directory and more files to our project.

With the latest files generated, let's create a new file called urls.py in our app directory.

#the_weather/weather/urls.py

from django.urls import path

urlpatterns = [
]

This file is similar to the urls.py in our the_weather directory. The difference is that this urls.py file contains all the URLs that are relevant to the app itself.

We're not specifying a URL yet, but we can set up the project to recognize our app and route any URLs specific to our app to the app urls.py file.

First, go to the INSTALLED_APPS list and add this app to the list.

#the_weather/the_weather/settings.py
...

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

...

This lets Django know we want to use the weather app in our project. By doing this, Django will know where to look for migrations and the URLs.

Next, we need to modify the original urls.py to point to our app urls.py file. To do that, we add a line under the existing path for the admin dashboard. We also need to import 'include' so we can point to our app urls.py file.

#the_weather/the_weather/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('weather.urls')),
]

The empty string means that we won't use an endpoint for the entry point to our app. Instead we'll let the app handle any specific endpoints. We could have easily put something like path('weather/', ...), which would have meant we would have to type 127.0.0.1:8000/weather/ to get anything associated with our weather app. But since our project is simple, we won't be doing that here.

Adding the Template and View

Now for the first interesting thing we're going to do. We need to add the template to our project.

A template in Django is just an HTML file that allows for extra syntax that makes the template dynamic. We'll be able to do things like add variables, if statements, and loops, among other things.

To start, I have an HTML file that's free any template syntax, but this will be enough for us to start.

We're going to create a template directory to put this file in.

cd weather
mkdir templates && cd templates
mkdir weather

We also created another directory with the same name as our app. We did this because Django combines all the templates directories from the various apps we have. To prevent filenames being duplicated, we can use the name of our app to prevent the duplicates.

Inside of the weather directory, create a new file called index.html. This will be our main template. Here's the HTML we'll use for the template.

<!-- the_weather/weather/templates/weather/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>What's the weather like?</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.css" />
</head>
<body>
    <section class="hero is-primary">
        <div class="hero-body">
            <div class="container">
                <h1 class="title">
                    What's the weather like?
                </h1>
            </div>
        </div>
    </section>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-offset-4 is-4">
                    <form method="POST">
                        <div class="field has-addons">
                            <div class="control is-expanded">
                                <input class="input" type="text" placeholder="City Name">
                            </div>
                            <div class="control">
                                <button class="button is-info">
                                    Add City
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </section>
    <section class="section">
        <div class="container">
            <div class="columns">
                <div class="column is-offset-4 is-4">
                    <div class="box">
                        <article class="media">
                            <div class="media-left">
                                <figure class="image is-50x50">
                                    <img src="http://openweathermap.org/img/w/10d.png" alt="Image">
                                </figure>
                            </div>
                            <div class="media-content">
                                <div class="content">
                                    <p>
                                        <span class="title">Las Vegas</span>
                                        <br>
                                        <span class="subtitle">29° F</span>
                                        <br> thunderstorm with heavy rain
                                    </p>
                                </div>
                            </div>
                        </article>
                    </div>
                </div>
            </div>
        </div>
    </section>
    <footer class="footer">
    </footer>
</body>
</html>

Now that we have our template created, let's create a view and URL combination so we can actually see this in our app.

Views in Django are either functions or classes. In our case since we're creating a simple view, we'll create a function. Add this function to your views.py:

#the_weather/weather/views.py

from django.shortcuts import render

def index(request):
    return render(request, 'weather/index.html') #returns the index.html template

We're naming our view 'index' because it will be at the index of our app, which is the root URL. To have the template render, we return request, which is necessary for the render function, and the name of the template file we want to render, in this case weather/index.html.

Let's add the URL that will send the request to this view. In the urls.py for the app, update the urlpatterns list.

#the_weather/weather/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),  #the path for our index view
]

This allows us to reference the view we just created.

Django is going to match any URL without an endpoint and route it to the view function we created.

Go back to your project root, start the server, and go to 127.0.0.1:8000 again.

python manage.py runserver

Creating a Weather App in Django Using Python Requests

What we see now is just the result of the HTML you have in index.html file. You'll see an input to add a city and the weather for Las Vegas. However, the form doesn't work and the weather is just a placeholder, but don't worry, because we'll be creating those for this app.

Using the Weather API

What we want to do now is sign up for the Open Weather Map API. This will allow us to get the actual weather for any cities that we add in our app.

Go to the site, create an account and then go to the API keys on their dashboard. Enter a name and generate a new API key. This key will allow us to use the API to get the weather.

Creating a Weather App in Django Using Python Requests

The one endpoint we'll use is below, so you can see the actual data that gets returned by modifying the following URL with your API key and navigating to the URL in your browser. It may take a few minutes for your API key to become active, so if it doesn't work at first, try again in after a few minutes.

http://api.openweathermap.org/data/2.5/weather?q=las%20vegas&units=imperial&appid=YOUR_APP_KEY

With that, let's add in a request to get the data into our app.

First, we'll need to install requests so we can call the API from inside our app.

pipenv install requests

Let's update our index view to send a request to the URL we have.

#the_weather/weather/views.py

from django.shortcuts import render
import requests

def index(request):
    url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'
    city = 'Las Vegas'
    city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types

    return render(request, 'weather/index.html') #returns the index.html template

With those three lines, we're adding the URL that will send a request to. We'll make the part for the city a placeholder for when we allow users to add their own cities.

For now we'll set the city to be Las Vegas, but later this will be set to the cities from the database.

Finally, we'll send the request to the URL using the city and get the JSON representation of that city. If we print that to the console we can see the same data we saw when we put the URL in our address bar.

If you start your server again and reload the page, you'll see the data get printed to your console.

Creating a Weather App in Django Using Python Requests

Displaying the Data in the Template

Next, we need to pass the data to the template so it can be displayed to the user.

Let's create a dictionary to hold all of the data we need. Of the data returned to us, we need temp, description, and icon.

#the_weather/weather/views.py

def index(request):
    ...
    weather = {
        'city' : city,
        'temperature' : city_weather['main']['temp'],
        'description' : city_weather['weather'][0]['description'],
        'icon' : city_weather['weather'][0]['icon']
    }

    return render(request, 'weather/index.html') #returns the index.html template

Now that we all the information we want, we can pass that to the template. To pass it to the template, we'll create a variable called context. This will be a dictionary that allows us to use its values inside of the template.

#the_weather/weather/views.py

def index(request):
    ...
    context = {'weather' : weather}
    return render(request, 'weather/index.html', context) #returns the index.html template

And then in render, we'll add the context as the third argument.

With the weather data added inside of context, let's go to the template to add the data.

Inside of the template, all we need to do is modify the HTML to use variables instead of the values I typed in. Variables will use {{ }} tags, and they will reference anything inside of your context dictionary.

Note that Django converts dictionary keys so you can only access them using dot notation. For example, weather.city will give us the city name. We don't use weather['city'] like we would in Python.

Find the box div, and update it to this:

<!-- the_weather/weather/templates/weather/index.html -->
<div class="box">
    <article class="media">
        <div class="media-left">
            <figure class="image is-50x50">
                <img src="http://openweathermap.org/img/w/{{ weather.icon }}.png" alt="Image">
            </figure>
        </div>
        <div class="media-content">
            <div class="content">
                <p>
                    <span class="title">{{ weather.city }}</span>
                    <br>
                    <span class="subtitle">{{ weather.temperature }}° F</span>
                    <br> {{ weather.description }}
                </p>
            </div>
        </div>
    </article>
</div>

With all the variables replaced, we should now see the current weather for our city.

Creating a Weather App in Django Using Python Requests

Great! Now we can see the weather for one city, but we had to hard code the city. What we want to do now is pull from the database and show the cities that are in our database.

To do that, we'll create a table in our database to hold the cities that we want to know the weather for. We'll create a model for this.

Go to the models.py in your weather app, and add the following:

#the_weather/weather/models.py

from django.db import models

class City(models.Model):
    name = models.CharField(max_length=25)

    def _str_(self): #show the actual city name on the dashboard
        return self.name

    class Meta: #show the plural of city as cities instead of citys
        verbose_name_plural = 'cities'

This will create a table in our database that will have a column called name, which is the name of the city. This city will be a charfield, which is just a string.

To get these changes in the database, we have to run makemigrations to generate the code to update the database and migrate to apply those changes. So let's do that now.

python manage.py makemigrations
python manage.py migrate

We need to make it to where we can see this model on our admin dashboard. To do that, we need to register it in our admin.py file.

#the_weather/weather/admin.py

from django.contrib import admin
from .models import City

admin.site.register(City)

You'll see the city as an option on the admin dashboard.

Creating a Weather App in Django Using Python Requests

We can then go into the admin dashboard and add some cities. I'll start with three: London, Tokyo, and Las Vegas.

Creating a Weather App

With the entries in the database, we need to query these entries in our view. Start by importing the City model and then querying that model for all objects.

#the_weather/weather/views.py

from django.shortcuts import render
import requests
from .models import City
#the_weather/weather/views.py

def index(request):
    url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'
    cities = City.objects.all() #return all the cities in the database
    ...

Since we have the list of cities, we want to loop over them and get the weather for each one and add it to a list that will eventually be passed to the template.

This will just a variation of what we did in the first case. The other difference is we are looping and appending each dictionary to a list. We'll remove the original city variable in favor a city variable in the loop.

#the_weather/weather/views.py

def index(request):
    ...
    weather_data = []

    for city in cities:

        city_weather = requests.get(url.format(city)).json() #request the API data and convert the JSON to Python data types

        weather = {
            'city' : city,
            'temperature' : city_weather['main']['temp'],
            'description' : city_weather['weather'][0]['description'],
            'icon' : city_weather['weather'][0]['icon']
        }

        weather_data.append(weather) #add the data for the current city into our list

    context = {'weather_data' : weather_data}
    ...

Cool, so we have the data. Now let's update the context to pass this list instead of a single dictionary.

#the_weather/weather/views.py

    ...
    context = {'weather_data' : weather_data}
    ...

Next, inside of the template, we need to loop over this list and generate the HTML for each city in the list. To do this, we can put a for loop around the HTML that generates a single box for the city.

<!-- the_weather/weather/index.html -->
<div class="column is-offset-4 is-4">
    {% for weather in weather_data %}
    <div class="box">
        <article class="media">
            <div class="media-left">
                <figure class="image is-50x50">
                    <img src="http://openweathermap.org/img/w/{{ weather.icon }}.png" alt="Image">
                </figure>
            </div>
            <div class="media-content">
                <div class="content">
                    <p>
                        <span class="title">{{ weather.city }}</span>
                        <br>
                        <span class="subtitle">{{ weather.temperature }}° F</span>
                        <br> {{ weather.description }}
                    </p>
                </div>
            </div>
        </article>
    </div>
    {% endfor %}
</div>

Awesome! Now we can see the data for all the cities we have in the database.

Creating the Form

The last thing we want to do is allow the user to add a city directly in the form.

To do that, we need to create a form. We could create the form directly, but since our form will have exactly the same field as our model, we can use a ModelForm.

Create a new file called forms.py.

#the_weather/weather/forms.py

from django.forms import ModelForm, TextInput
from .models import City

class CityForm(ModelForm):
    class Meta:
        model = City
        fields = ['name']
        widgets = {
            'name': TextInput(attrs={'class' : 'input', 'placeholder' : 'City Name'}),
        } #updates the input class to have the correct Bulma class and placeholder

To view the form, we need to create it in our view and pass it to the template.

To do that, let's update the index video to create the form. We'll replace the old city variable at the same time since we no longer need it. We also need to update the context so the form gets passed to the template.

#the_weather/weather/views.py

def index(request):
    ...
    form = CityForm()

    weather_data = []
    ...
    context = {'weather_data' : weather_data, 'form' : form}

Now in the template, let's update the form section to use the form from our view and a csrf_token, which is necessary for POST requests in Django.

<form method="POST">
    {% csrf_token %}
    <div class="field has-addons">
        <div class="control is-expanded">
            {{ form.name }}
        </div>
        <div class="control">
            <button class="button is-info">
                Add City
            </button>
        </div>
    </div>
</form>

With the form in our HTML working, we now need to handle the form data as it comes in. For that, we'll create an if block checking for a POST request. We need to add the check for the type of request before we start grabbing the weather data so we immediately get the data for the city we add.

#the_weather/weather/views.py

def index(request):
    cities = City.objects.all() #return all the cities in the database

    url = 'http://api.openweathermap.org/data/2.5/weather?q={}&units=imperial&appid=YOUR_APP_KEY'

    if request.method == 'POST': # only true if form is submitted
        form = CityForm(request.POST) # add actual request data to form for processing
        form.save() # will validate and save if validate

    form = CityForm()
    ...

By passing request.POST, we'll be able to validate the form data.

Now you should be able to type in the name of a city, click add, and see it show up. I'll add Miami as the next city.

Creating a Weather App in Django

When we drop out of the if block, the form will be recreated so we can add another city if we choose. The rest of the code will behave in the same way.

Conclusion

And that's it! We now have a way to keep track of the weather for multiple cities in our app.

In this article, we had to work with various parts of Django to get this working: views, models, forms, and templates. We also had to use the Python library requests to get the actual weather data. So even though the app is simple, you'll use many of the same concepts in apps with more complexity.