Replace all occurrences in a string – Javascript

To replace all the occurrences in a string in Javascript, we will use the following method.

For example, you have the following string variable.

let string = "adnan_tech_com"

And you want to replace all underscores with a white space.

You can use the following code to replace all occurrences of underscores with a whitespace.

string = string.split("_").join(" ") // adnan tech com

Explanation

First, you need to split the string by underscore. It will return an array.

let string = "adnan_tech_com"

string = string.split("_") // ["adnan", "tech", "com"]

Then we can join the array by whitespace.

let string = "adnan_tech_com"

string = string.split("_")

string = string.join(" ") // adnan tech com

Don’t use replace()

You should not use “replace” function because it will replace only the first occurrence in a string.

let string = "adnan_tech_com"

string = string.replace("_", " ") // adnan tech_com

Checkout our more tutorials on Javascript.

How to fix CORS error in Socket IO NodeJS

In this short tutorial, I will show you how you can fix CORS error in socket IO in NodeJS.

First, you need to use the socket IO import statement in following way:

const socketIO = require("socket.io")(http, {
	cors: {
		origin: "*"
	}
})

Then, with your Express app instance, you can set the following headers.

// Add headers before the routes are defined
app.use(function (req, res, next) {

    // Website you wish to allow to connect
    res.setHeader("Access-Control-Allow-Origin", "*")

    // Request methods you wish to allow
    res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE")

    // Request headers you wish to allow
    res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,content-type,Authorization")

    // Set to true if you need the website to include cookies in the requests sent
    // to the API (e.g. in case you use sessions)
    res.setHeader("Access-Control-Allow-Credentials", true)

    // Pass to next layer of middleware
    next()
})

Create middleware for specific route – Python

If you are creating an API in Python, and came across a problem where you have to create a middleware but for only specific route. For example, you are creating a user authentication system and want to create a middleware that checks if the user is logged-in. But you want to use that middleware for only few routes, not for all routes. Then this tutorial is for you.

This can be done by creating subapps in Python. To create a subapp in Python, first we need to create a file where we will save the global variable of our subapp.

Create a file, let’s say config.py, and write the following code in it.

# config.py

from fastapi import FastAPI

my_middleware_app = FastAPI()

Now create a file for our middleware, I am naming it my_middleware.py. Following will be the code of this file.

from fastapi import Request
from config import my_middleware_app

from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder

@my_middleware_app.middleware("http")
async def my_func(request: Request, call_next):
	if "Authorization" in request.headers:
		print(request.headers["Authorization"])

		request.state.name = "Adnan"
		response = await call_next(request)
		return response
	else:
		return JSONResponse(content=jsonable_encoder("Authorization header not provided."))

Explanation:

  1. First, it imports the subapp “my_middleware_app” from “config” module.
  2. Then it imports “JSONResponse” and “jsonable_encoder” from “fastapi” modules. They will be required to send the response back to the client.
  3. Then we are creating a middleware using our subapp “my_middleware_app”.
  4. In this, we are checking if the request has “Authorization” header provided.
    • To learn more about authorization in Python, check our tutorial on user authentication.
  5. If not, then we are sending an error.
  6. If provided, then we are attaching a “name” variable with the request and pass it to the route.

Now let me show you, how the route can use this middleware and how route can access the “name” variable.

Following will be the content of our main.py file where the route will be created.

# main.py

from fastapi import FastAPI, Request
from config import my_middleware_app
import my_middleware

app = FastAPI()

@my_middleware_app.post("/my-route")
def my_route(request: Request):
	return request.state.name

app.mount("/", my_middleware_app)

We first imported the subapp module and the middleware.

Then we created an instance of FastAPI (the main app).

After that, we are creating a post route using our subapp. In this route, we are using the “name” variable we created in our middleware.

To send value from middleware to route, we can use request.state object.

And lastly, we are mounting the subapp to our main app.

Creating a middleware and using it just for specific route in Python is a bit confusing sometimes. So if you face any problem in following this, please do not hesitate to get in touch with me.

Create global variable between modules – Python

In this tutorial, we will show you how you can create global variable and access them in different modules in Python.

First, you need to create a file, let’s say “config.py“. And write all your global variables in it.

# config.py

my_name = "Adnan"

Here, I have created a global variable my_name. In order to access it in any other module, simply import it. Then you can use them as normal variables.

# any_other_module.py

# method 1

from config import my_name

print(my_name)

There is another method to import the module.

# any_other_module.py

# method 2

import config

print(config.my_name)

That is how you can create global variable and use it in multiple modules in Python. Kindly let me know if you face any problem in following this.

Get age from date of birth – Javascript

Suppose you are given a date of birth of any user and you have to get his age from it. You can do it in Javascript using the following code:

const date = new Date("1993-07-27")
const current_date = new Date()

let age = current_date.getTime() - date.getTime()
// 948161820692

age = new Date(age)
// 2000-01-18T02:17:18.105Z

age = age.getFullYear()
// 2000

age = age - 1970
// 30

Create a URL shortener app in Vue JS, Python, Mongo DB

In this tutorial, we will create a URL shortener app in Vue JS, Python and Mongo DB. We will use Vue JS as frontend, Python as backend and Mongo DB as database.

We will be creating a single page application in Vue JS 3, FastAPI for creating APIs in Python and standard Mongo DB for storing data.

User will enter a URL and the app will create a shorter URL of it. User can share that short URL on social media. Whenever someone access that short URL, we will show ads to him for 5 seconds. Then he will be able to move to the actual URL.

User can see how many people have clicked on his shorten URL and how many have accessed the real URL.

We will create the frontend in Vue JS 3, it will be a single page application (SPA). The backend will be in Python, we will be using FastAPI.

Add URL – Vue JS

The first step is to show user a form where he can enter his URL to shorten. So go ahead and create a folder anywhere in your computer (I have created on desktop). And inside that folder, create 2 more folders named “web” and “api”.

All our frontend code will go in “web” and all our backend code will go in “api”. Now open your command prompt (CMD) or terminal in your “web” folder and run the following command to install Vue JS.

> npm install -g @vue/cli

Then we will create an SPA in that folder.

> vue create .

If asked for Vue JS version, select Vue JS 3. Then run the following command to start Vue JS on localhost.

> npm run serve

You can access your app from http://localhost:8080/

Now go in your “web/src/components” and delete the “HelloWorld.vue” file. And create a file named “HomeComponent.vue”. Following will be the content of that file:

<template>
	HomeComponent
</template>

<script>
	export default {
		name: "HomeComponent"
	}
</script>

Open “src/main.js” and remove the “HelloWorld” component occurrences from there too.

In your components folder, create a folder named “layouts” and create 2 files in it: “AppHeader.vue” and “AppFooter.vue”. Following will be the content of these files:

// AppHeader.vue

<template>
	AppHeader
</template>

<script>
	export default {
		name: "AppHeader"
	}
</script>

// AppFooter.vue
<template>
	AppFooter
</template>

<script>
	export default {
		name: "AppFooter"
	}
</script>

Then run the following command to install “vue-router” that will be used for navigation, “sweetalert2” for displaying popups and “axios” for making AJAX calls.

npm install vue-router sweetalert2 axios

Then in your “main.js”, initialize the vue-router module.

import { createRouter, createWebHistory } from "vue-router"
import HomeComponent from "./components/HomeComponent.vue"

const app = createApp(App)

const routes = [
	{ path: "/", component: HomeComponent }
]

const router = createRouter({
	history: createWebHistory(),
	routes
})

app.use(router)
app.mount('#app')

Open your “web/src/App.vue” and replace the existing content with the following.

<template>
  <app-header />
    <router-view />
  <app-footer />
</template>

<script>

import AppHeader from "./components/layouts/AppHeader.vue"
import AppFooter from "./components/layouts/AppFooter.vue"

export default {
  name: 'App',
  components: {
    AppHeader,
    AppFooter
  }
}
</script>

After that, download Bootstrap 5 and paste the CSS and JS files in your “web/src/assets” folder. Then include them in your AppHeader component.

import "../../assets/css/bootstrap.css"
import "../../assets/js/jquery.js"
import "../../assets/js/bootstrap.js"

If you get any error regarding popper, just run the following commands.

> npm install @popperjs/core
> npm remove @vue/cli-plugin-eslint

Learn more about them in here.

Then open your HomeComponent and create a form inside <template> tag. The form simply have 1 field to enter the URL and a submit button.

<div class="container">
	<div class="row">
		<div class="offset-md-3 col-md-6">
			<form v-on:submit.prevent="shorten_url">
				<div class="form-group">
					<label class="form-label">Enter URL</label>
					<input type="url" name="url" placeholder="Enter URL" class="form-control" required />
				</div>

				<input type="submit" class="btn btn-primary" style="margin-top: 10px;" value="Shorten" />
			</form>

			<!-- [table goes here] -->
		</div>
	</div>
</div>

Then create a function “shorten_url” in your <script> tag in HomeComponent.

import axios from "axios"
import swal from "sweetalert2"

export default {
	name: "HomeComponent",

	methods: {
		async shorten_url() {
			const form = event.target
			const formData = new FormData(form)
			formData.append("timezone", Intl.DateTimeFormat().resolvedOptions().timeZone)

			try {
				const response = await axios.post(
					this.$api_url + "/shorten-url",
					formData
				)

				if (response.data.status == "success") {
					// [on url shortened success]
				} else {
					swal.fire("Error", response.data.message, "error")
				}
			} catch (exp) {
				console.log(exp)
			}
		}
	}
}

In your “main.js” add the following line that defines the URL of our Python API.

app.config.globalProperties.$api_url = "http://127.0.0.1:8000"

In the above function, we are sending form data to the server. We are also sending current timezone, so the server can return the time (in local timezone) when the URL was added.

Add URL – Python, Mongo DB

So the view is created, now we need to create our backend API that will handle this request.

Making sure you have installed Python 3 in your system, run the following commands in your “api” folder.

pip3 install fastapi uvicorn pymongo python-multipart

Create a file named api.py and write the following code in it:

import random, string
from fastapi import FastAPI, Form
from typing_extensions import Annotated
from fastapi.middleware.cors import CORSMiddleware
from pymongo import MongoClient
from bson.objectid import ObjectId
from datetime import datetime, timezone as timezone_module
from dateutil import tz

MONGO_CONNECTING_STRING = "mongodb://localhost:27017"
client = MongoClient(MONGO_CONNECTING_STRING)
db_name = "url_shortener"
db = client[db_name]

app = FastAPI()

app.add_middleware(
	CORSMiddleware,
	allow_origins=["*"]
)

@app.post("/shorten-url")
def shorten_url(url: Annotated[str, Form()], timezone: Annotated[str, Form()]):

	while True:
		random_characters = "".join(random.choice(string.ascii_lowercase) for _ in range(8))
		url_obj = db["urls"].find_one({
			"hash": random_characters
		})

		if (url_obj == None):
			break

	inserted_doc = {
		"_id": ObjectId(),
		"url": url,
		"hash": random_characters,
		"views": 0,
		"clicks": 0,
		"created_at": datetime.now(timezone_module.utc)
	}

	db["urls"].insert_one(inserted_doc)
	inserted_doc["_id"] = str(inserted_doc["_id"])
	inserted_doc["created_at"] = convert_utc_to_local(timezone, inserted_doc["created_at"])

	return {
		"status": "success",
		"message": "URL has been shortened.",
		"url": inserted_doc
	}

def convert_utc_to_local(timezone, utc):
	# Hardcode zones:
	from_zone = tz.gettz('UTC')
	to_zone = tz.gettz(timezone)

	# Tell the datetime object that it's in UTC time zone since 
	# datetime objects are 'naive' by default
	utc = utc.replace(tzinfo=from_zone)

	# Convert time zone
	utc = utc.astimezone(to_zone).strftime("%b %d, %Y %H:%M:%S")

	return utc

To start the API, run the following command in your “api” folder:

uvicorn api:app --reload

You can access it from here:

http://127.0.0.1:8000

You might see it blank and that’s okay. Because it will be accessed via AJAX calls.

Explanation:

First, we are making connection with Mongo DB. Then we are initializing FastAPI and setting CORS middleware to prevent CORS error.

After that, we are creating a function that will handle the request. It accepts URL and timezone.

It will generate random 8 characters and make sure they are unique in database using do-while loop.

Then it will insert the record in database. And in order to return the inserted document to the client side, we need to convert the ObjectId to string.

Date & time will be stored in UTC in database. But to return to client side, we have to convert UTC to user’s local timezone. So we have created a separate function “convert_utc_to_local” for that.

Show all added URLs – Vue JS

In your HomeComponent, write the following code in [table goes here] section.

<table class="table table-bordered" style="margin-top: 50px;">
	<thead>
		<tr>
			<th>URL</th>
			<th>Views</th>
			<th>Clicks</th>
			<th>Created at</th>
		</tr>
	</thead>

	<tbody>
		<tr v-for="(url, index) in urls">
			<td>
				<router-link v-bind:to="'/url/' + url.hash" v-text="url.hash"></router-link>
			</td>
			<td v-text="url.views"></td>
			<td v-text="url.clicks"></td>
			<td v-text="url.created_at"></td>
		</tr>
	</tbody>
</table>

Then in your <script> tag, initialize an empty array.

data() {
	return {
		urls: []
	}
},

And write the following code at [on url shortened success] section:

this.urls.unshift(response.data.url)

Add a “mounted” event in your Vue JS object.

mounted() {
	this.get_data()
}

After that, create the following method inside your “methods” object.

async get_data() {
	const formData = new FormData()
	formData.append("timezone", Intl.DateTimeFormat().resolvedOptions().timeZone)

	try {
		const response = await axios.post(
			this.$api_url + "/fetch-urls",
			formData
		)

		if (response.data.status == "success") {
			this.urls = response.data.urls
		} else {
			swal.fire("Error", response.data.message, "error")
		}
	} catch (exp) {
		console.log(exp)
	}
}

Fetch all URLs – Python, Mongo DB

Now we need to create an API in Python that will fetch all URLs from Mongo DB. Write the following code in your “api/api.py” file.

@app.post("/fetch-urls")
def fetch_urls(timezone: Annotated[str, Form()]):
	urls = db["urls"].find().sort("created_at", -1)

	url_arr = []
	for url in urls:
		url["_id"] = str(url["_id"])
		url["created_at"] = convert_utc_to_local(timezone, url["created_at"])

		url_arr.append(url)

	return {
		"status": "success",
		"message": "Data has been fetched.",
		"urls": url_arr
	}

Test the app now and you will see all your added URLs. Now whenever a URL is clicked, we will show a new page where user will have to wait for 5 seconds to access the real URL.

Access the URL – Vue JS

In your “web/src/components” folder, create a file named “URLComponent.vue” and write the following code in it:

<template>
	URLComponent
</template>

<script>

	export default {
		name: "URLComponent"
	}
</script>

Register it in your “main.js” file.

import URLComponent from "./components/URLComponent.vue"

And add it in “routes” array too.

{ path: "/url/:url", component: URLComponent }

Back to your URLComponent, write the following code inside <template> tag.

<div class="container">
	<div class="row">
		<div class="col-md-12">
			<div class="float-end" style="padding: 15px;
			    border-radius: 5px;
			    background-color: lightblue;
			    cursor: pointer;">
			    <span v-if="remaining_seconds > 0">
			    	Redirecting in <span v-text="remaining_seconds"></span> seconds
			    </span>
				
			    <span v-else v-on:click="goto_website">Go to website</span>
			</div>
		</div>
	</div>
</div>

This will show a text that will show the number of seconds remaining till user has to wait. When the time is over, it will show a clickable text which when clicked, should move the user to the actual URL.

import axios from "axios"
import swal from "sweetalert2"

export default {
	name: "URLComponent",

	data() {
		return {
			url: this.$route.params.url,
			remaining_seconds: 5,
			url_obj: null,
			interval: null
		}
	},

	methods: {
		async goto_website() {
			if (this.url_obj == null) {
				return
			}

			window.location.href = this.url_obj.url
		},

		async get_data() {
			const formData = new FormData()
			formData.append("url", this.url)

			try {
				const response = await axios.post(
					this.$api_url + "/get-url",
					formData
				)

				if (response.data.status == "success") {
					this.url_obj = response.data.url
				} else {
					swal.fire("Error", response.data.message, "error")
				}
			} catch (exp) {
				console.log(exp)
			}
		}
	},

	mounted() {
		const self = this
		this.get_data()

		setTimeout(function () {
			self.interval = setInterval(function () {
				self.remaining_seconds--

				if (self.remaining_seconds <= 0) {
					clearInterval(self.interval)
				}
			}, 1000)
		}, 500)
	}
}

When this component is mounted, we will call “get_data” function that will fetch the single URL data from Python API.

Also, it will start a countdown timer from 5. Once timer hits 0, you can click the button and go to your actual URL.

Fetch single URL – Python, Mongo DB

Create the following API in your “api/api.py” file.

@app.post("/get-url")
def get_url(url: Annotated[str, Form()]):

	url = db["urls"].find_one({
		"hash": url
	})

	if (url == None):
		return {
			"status": "error",
			"message": "URL not found."
		}

	url["_id"] = str(url["_id"])

	return {
		"status": "success",
		"message": "Data has been fetched.",
		"url": url
	}

This will fetch the single URL from Python API.

Number of clicks on Shorten URL

When you share the shorten URL with your friends, you might want to know how many have clicked the shorten URL and how many clicked the actual URL.

To increment number of clicks on shorten URL, we will simply go to “api.py” function “get_url” and add the following code before converting ObjectId “_id” to string.

db["urls"].find_one_and_update({
	"_id": url["_id"]
}, {
	"$inc": {
		"views": 1
	}
})

Test now and you will see whenever someone access your shorten URL page, your “views” gets incremented in HomeComponent.

Number of clicks on actual URL

In order to see how many has clicked on your actual URL, you need to open your “URLComponent.vue” file. Add the following lines in your “goto_website” function before the “window.location.href” line.

const formData = new FormData()
formData.append("url", this.url)
window.navigator.sendBeacon((this.$api_url + "/url-clicked"), formData)

Then create its API in Python that will handle this request.

@app.post("/url-clicked")
def url_clicked(url: Annotated[str, Form()]):
	db["urls"].find_one_and_update({
		"hash": url
	}, {
		"$inc": {
			"clicks": 1
		}
	})

Now whenever someone visit the actual URL, the “clicks” counter gets incremented.

Header and Footer

Write the following code insde <template> tag of your AppHeader component.

<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <div class="container-fluid">
    <router-link class="navbar-brand" to="/">URL Shortener</router-link>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav me-auto mb-2 mb-lg-0">
        <li class="nav-item">
          <router-link class="nav-link active" aria-current="page" to="/">Home</router-link>
        </li>
      </ul>
    </div>
  </div>
</nav>

And change your AppFooter component to the following.

<template>
	<footer class="container-fluid" style="margin-top: 50px; background-color: #e9e9e9; padding: 25px;">
		<p class="text-center" style="margin-bottom: 0px;">
			&copy;<span v-text="year"></span>&nbsp;
			adnan-tech.com
		</p>
	</footer>
</template>

<script>
	export default {
		name: "AppFooter",

		data() {
			return {
				year: new Date().getFullYear()
			}
		}
	}
</script>

So this is how you can create a URL shortener app using Vue JS as frontend, Python as backend and Mongo DB as database. If you face any problem in following this, kindly do let me know.

Python API development

In this article, we will talk about basic Python API development.

Python API development

Install python3. Download from its official website and install.

Create API by first installing following modules:

pip3 install fastapi
pip3 install uvicorn

Create a file named api.py and write the following code in it:

from fastapi import FastAPI
app = FastAPI()

@app.get("/my-first-api")
def hello():
	return ("Hello world !")

if __name__ == "__main__":
	uvicorn.run(app, port=8000, host="127.0.0.1")

Run the following command in terminal to start the API:

uvicorn api:app --reload

Access it from browser:

http://127.0.0.1:8000/my-first-api

CORS error

If you are having CORS error, you can make the following changes in your code:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
	CORSMiddleware,
	allow_origins=["*"]
)

Connect Python with Mongo DB

To connect your Python application with Mongo DB, first install pymongo in your server by running the following command:

> pip3 install pymongo

Then you need to import it in your file:

from pymongo import MongoClient

MONGO_CONNECTING_STRING = "mongodb://localhost:27017"
client = MongoClient(MONGO_CONNECTING_STRING)
db = client["your_database_name"]

To insert a document in collection, write the following line:

db["your_collection"].insert_one({
	"name": "Adnan"
})

Form data

Let’s say you have a Javascript code that sends an AJAX request to your Python server.

const formData = new FormData()
formData.append("website", "adnan-tech.com")

Then, in order to get it in your Python API, first you need to run the following command to install “python-multipart” module:

pip3 install python-multipart

Then include the “Form” and “Annotated” module.

from fastapi import FastAPI, Form
from typing_extensions import Annotated

Then in your post API method parameter, define each form data value and its type.

@app.post("/my-api")
async def my_api(website: Annotated[str, Form()]):

	print(url)

Installing Django framework

For Python API development you can also use Django framework. First, you need to install Django framework in your project’s root directory:

pip3 install django

Then you can verify it by checking the version:

python3 -m django --version

You can also verify the version from following command as well:

django-admin --version

Then we will create our django application:

django-admin startproject ecommerce-website

A new folder will be created named “ecommerce-website”. If you go inside this folder, you will find files named “manage.py” and other files along with a directory named same as “ecommerce-website”.

Now enter in the directory “ecommerce-website” and run the following command:

python3 manage.py startapp ecommerce

It will create a directory named “ecommerce”. Now run the following command to start the server:

python3 manage.py runserver

Now you can access your website by running the following URL in the browser:

http://127.0.0.1:8000/

You can access admin panel from:

http://127.0.0.1:8000/admin

It will ask for username and password. You can set it by first running the migration:

python3 manage.py migrate

Then you can create a super user.

python3 manage.py createsuperuser

Create app in Django

Run the following command at the root of your project:

python3 manage.py startapp pages

This will create a folder named “pages”.

Now open “ecommerce/settings.py” and add our app to the “INSTALLED_APPS” array.

INSTALLED_APPS = [
    ...
    "pages"
]

You can get your app name by opening the file “pages/apps.py”.

To create a view, open “pages/views.py” and add the following lines in it:

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.

def index(request):
	return HttpResponse("<h1>Hello world</h1>")

To configure the URL, create a file named “urls.py” inside “pages” folder and write the following code in it:

from django.urls import path
from . import views

urlpatterns = [
	path("", views.index, name="index")
]

Now open your project’s root “ecommerce/urls.py” and add the following line in it:

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

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

If you check your browser now at: http://127.0.0.1:8000/, you will see your message “Hello world” in it.

Creating models in Django

To create a model, open your app’s “models.py” file. In my case, it is “pages/models.py”. And write the following code in it:

class Page(models.Model):
	title = models.CharField(max_length = 255)
	content = models.TextField("Content", blank = True)

	def __str__(self):
		return self.title

It will create 2 fields (title and content). The “__str__” function is created to display the page title on admin panel where page listing is displayed.

Then you have to create its migration and migrate it. So run the following commands one-by-one:

python3 manage.py makemigrations pages
python3 manage.py migrate

Then in order to display it on admin panel, open your “pages/admin.py” file and add the following code in it:

from .models import Page

class PageAdmin(admin.ModelAdmin):
	list_display = ("title", "content",)
	ordering = ("title",)
	search_fields = ("title", "content",)

# Register your models here.
admin.site.register(Page, PageAdmin)

This will first import our Page model. Then it will create a class to handle it on admin panel. We will display 2 columns (title and content) on admin panel listing.

The ordering will be done by title field only.

And a search field will be displayed, from where user can search pages by their title or content.

At the end, we are registering both of these classes (Page and PageAdmin) to the admin panel.

Now if you go to your admin panel, you will see an option to manage pages.

Templating

First create a folder named “templates” in your “myEcommerce” folder.

Then goto your project’s “settings.py” file and first import the os module at the top of it.

import os

Then search for array “TEMPLATES”. Add your templates folder path in the DIRS array:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "myEcommerce/templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Also, add the following array after the STATIC_URL variable:

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "myEcommerce/static")
]

In your templates folder, create a file named “base.html”.

Write the following code in your base.html file:

{% load static %}

<link rel="stylesheet" type="text/css" href="{% static 'main.css' %}" />

<h1>My template loaded</h1>

Then in your “myEcommerce/static” folder, create a filed named “main.css” and write the following code in it:

h1 {
	color: red;
}

And finally, change your “def index(request)” function inside “pages/views.py” to the following:

def index(request):
	return render(request, "base.html")

If you run the browser now, you will see your content from base.html file. And also it will load css from main.css file.

Template inheritance

You can create child template that extends from parent template. This will be helpful while creating header, footers or sidebars etc.

For that, add the following code in your “base.html” file:

{% block content %}

{% endblock content %}

You can set any name to your block. Now create a folder named “pages” inside “pages/templates” folder. This is necessary because Django will search for your files inside the “templates” folder.

Then create a file named “index.html” in your “pages/templates/pages” folder. Following will be the code of this file:

{% extends "base.html" %}

{% block content %}

<p>Hi</p>

{% endblock content %}

It first extends from base template. So the content of “base.html” will be display on top and “block content” will be displayed where it is mentioned in “base.html” file.

Finally, in your “pages/views.py” make the following changes:

# return render(request, "base.html")
return render(request, "pages/index.html")

If you refresh your page now, you will first see the content of base template. Then of your “pages/index.html” file.

Model to view (Overriding the view)

To fetch data from model and pass it to view, first goto “pages/urls.py” and comment out the previous path() function we created earlier in this post.

And add the following 2 paths, one for home page and one for other pages appending in the URL.

path("", views.index, {
	"pagename": 1
}, name="home"),
path("<str:pagename>", views.index, name="index")

This will pass variable named “pagename” to the view from the URL. So we need to catch that variable.

Open “pages/views.py” and change your index function to the following:

from django.shortcuts import render
from django.http import HttpResponse
from . models import Page

# Create your views here.

def index(request, pagename):
	page = Page.objects.get(id = pagename)
	context = {
		"title": page.title,
		"content": page.content
	}
	return render(request, "pages/index.html", context)

We have added “pagename” as an argument in the index function definition. Then we are getting the record from Page model using ID. And finally we are passing the page object from database to our view render function.

Then in our “pages/templates/pages/index.html”, we can display these values:

<h2>{{ title }}</h2>

<p>{{ content }}</p>

If your content contains HTML tags, then Django by default will escape them to prevent you from attacker’s attempts to inject executable code into your website.

You can render HTML tags by disabling the auto-escaping like this:

{% autoescape off %}

<p>{{ content }}</p>

{% endautoescape %}

If you run “http://127.0.0.1:8000” in your browser now, you will see the first page. Because its ID is 1.

But if you try “http://127.0.0.1:8000/2”, you will see second page. Because now it matches with ID.

Creating menus

To display all pages as menu hyperlinks, first we need to fetch all pages from database. So in your “pages/views.py”, change the context variable to the following:

context = {
	"title": page.title,
	"content": page.content,
	"pages": Page.objects.all()
}

Then in your “myEcommerce/templates/base.html” file, create a block where the child will render it:

{% block pages %}

{% endblock pages %}

And finally in your “pages/templates/pages/index.html”, you can render them as following:

{% block pages %}

<ul>
	{% for page in pages %}

		<li>
			<a href="{{ page.id }}">
				{{ page.title }}
			</a>
		</li>

	{% endfor %}
</ul>

{% endblock pages %}

If you refresh the browser now, you will see a list of all pages created from admin panel. On clicking any, will display the content of that page.

So these are all the basics for Python API development. You can move advance from here. But this is enough to get you started in API development using Python.

For frontend, you can use Vue JS. You can get our list of tutorials on Vue JS as well.

Record and save audio from web – Javascript, Node JS, PHP

In this article, we are going to teach you, how you can record and save audio from web using Javascript. For saving audio files, we will teach you how you can do that with PHP and Node JS.

Let’s get started

First, we will create a folder named “record-audio-from-web”. Inside this folder, create a file named “index.html” and include fontawesome CDN in it. We will be displaying a microphone icon to start recording.

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />

Then we will create a microphone icon.

  1. Give it a unique ID so we can get it in Javascript.
  2. Attach an “onclick” listener that will be called whenever that icon is clicked.
  3. And set the cursor to pointer so user will know that this is clickable.
<i class="fa fa-microphone" id="icon-record-audio" onclick="recordAudio()" style="cursor: pointer;"></i>

Now in Javascript, we first have to create an instance of recorder.

let recorder = null

Get microphone permission

Then we will create that function that will be called when the microphone icon is clicked. This function will:

  1. Get the permission to access laptop’s microphone.
  2. Initialize a media recorder object.
  3. Start recording audio from microphone.
// function to record audio
async function recordAudio() {
    // get permission to access microphone
	navigator.permissions.query({name: 'microphone'})
		.then(function (permissionObj) {
			console.log(permissionObj.state)				
		})
		.catch(function (error) {
			console.log('Got error :', error);
		})

    // get recorder object
	recorder = await doRecordAudio()

    // start audio
	recorder.start()
}

Record audio

Then we will create “doRecordAudio” function that will handle all the recording and stoping mechanism.

function doRecordAudio() {
    return new Promise(function (resolve) {
        // get user audio media
        navigator.mediaDevices.getUserMedia({
            audio: true
        })
        .then(function (stream) {
            // [media recorder goes here]
        })
    })
}

After that, we need to create a media recorder object. Following code goes in the [media recorder goes here] section:

// create media recorder object
const mediaRecorder = new MediaRecorder(stream)

// save audio chunks in an array
const audioChunks = []
mediaRecorder.addEventListener("dataavailable", function (event) {
    audioChunks.push(event.data)
})

// [start and stop listener goes here]

This will create a media recorder object from stream and save all audio chunks (when available) in an array.

Then write the following code in [start and stop listener goes here] section to create start and stop listeners:

// create a start function
const start = function () {
    // [start listener goes here]
}

// create a stop function
const stop = function () {
    return new Promise(function (resolve) {
        // [stop listener goes here]
    })
}

// send the values back to promise
resolve({
    start,
    stop
})

This “start” function gets called from “recordAudio()” function.

Start recording audio

When the start function is called, we need to:

  1. Change the microphone icon to stop icon.
  2. Change onclick listener, so next time the icon is clicked, we will stop the recording.
  3. And play the audio.
  4. Tell the media to start recording.

Following code goes in the [start listener goes here] section:

// when recording starts, set the icon to stop
document.getElementById("icon-record-audio").className = "fa fa-stop-circle"

// on icon clicked
document.getElementById("icon-record-audio").onclick = async function() {
    // stop the recorder
    if (recorder != null) {
        const audio = await recorder.stop()

        // [play audio]

        // [get audio base64 string]
    }
}

// start media recorder
mediaRecorder.start()

If you test now, you will be able to record the audio. The microphone icon will be changed as well. But now you need to find a way to stop the recording.

Stop the recording

When you are done recording the audio, you can click the icon again to stop it. Following code goes in the [stop listener goes here] section. This will:

  1. Attach a listener that will be called when the recording is stopped.
  2. Change the icon back to microphone.
  3. Reset the onclick listener to its initial state.
  4. Convert the audio chunks array into a blob.
  5. Create URL object from blob.
  6. Create an audio object to play when required.
  7. And stop the media recorder.
// on recording stop listener
mediaRecorder.addEventListener("stop", function () {

    // change the icon back to microphone
    document.getElementById("icon-record-audio").className = "fa fa-microphone"

    // reset the onclick listener so when again clicked, it will record a new audio
    document.getElementById("icon-record-audio").onclick = async function() {
        recordAudio()
    }

    // convert the audio chunks array into blob
    const audioBlob = new Blob(audioChunks)

    // create URL object from URL
    const audioUrl = URL.createObjectURL(audioBlob)

    // create an audio object to play
    const audio = new Audio(audioUrl)
    const play = function () {
        audio.play()
    }

    // send the values back to the promise
    resolve({
        audioBlob,
        play
    })
})

// stop the media recorder
mediaRecorder.stop()

If you test now, you can record the audio and stop the audio. The icon will change from microphone to stop and then from stop to microphone.

Play the audio after recording

In order to play the audio you just recorded, write the following line in the [play audio] section:

audio.play()

“stop” function will return the promise containing the “new Audio” object and calling “play()” will play the audio.

Converting audio to base64

We are already sending audioBlob from “stop” function, so we can create base64 string from it. Write the following code in your [get audio base64 string] section:

// get audio stream
const reader = new FileReader()
reader.readAsDataURL(audio.audioBlob)
reader.onloadend = function() {
    // get base64
    let base64 = reader.result

    // get only base64 data
    base64 = base64.split(',')[1]

    // send base64 to server to save
    sendVoiceNote(base64)
}

This will create a base64 string fom audio.

Sending audio base64 to server

Now we will create a function that will call an AJAX to save this base64 string as audio.

function sendVoiceNote(base64) {
        // create an instance for AJAX
        var ajax = new XMLHttpRequest()

        // set request method as POST, set URL and set asynchronous to true
        ajax.open("POST", "http://localhost:8888/tutorials/record-audio-from-web/sendVoiceNote.php", true)

        // send base64 string to server
        const formData = new FormData()
        formData.append("base64", base64)
        ajax.send(formData)
}

Note: In your server, create a folder named “audios” where all audio files will be saved.

Saving audio file on server – PHP

First, we will teach you how can you save it using PHP. Create a file named “sendVoiceNote.php” and write the following code in it:

<?php

$base64 = $_POST["base64"];

$file_name = "audios/" . time() . ".webm";
file_put_contents($file_name, base64_decode($base64));

echo $file_name;

Try recording an audio again. When you stop the audio, you will see that a new file will be saved in your “audios” folder. You can listen to your audio in your favorite media player (VLC etc).

Saving audio file on server – Node JS

Now we will teach you, how you can save the file using Node JS. Create a Node JS project by running the following commands one-by-one:

> npm install express http express-formidable fs cors
> npm install -g nodemon
> nodemon server.js

Create a file named “server.js” and write the following code in it:

const express = require("express")
const app = express()

const expressFormidable = require("express-formidable")
app.use(expressFormidable())

const cors = require("cors")
app.use(cors())

const fileSystem = require("fs")
const http = require("http").createServer(app)

http.listen(3000, function () {
	app.post("/sendVoiceNote", async function (request, result) {
		const base64 = request.fields.base64

        const buffer = Buffer.from(base64, "base64")
        const voiceNote = "audios/" + new Date().getTime() + ".webm"
        await fileSystem.writeFileSync(voiceNote, buffer)

        result.send(voiceNote)
	})
})

In your client side, change the AJAX “open” function call from:

ajax.open("POST", "http://localhost/record-audio-from-web/sendVoiceNote.php", true)

To:

ajax.open("POST", "http://localhost:3000/sendVoiceNote", true)

So that’s it. That’s how you can record audio from web and save it in your server using Node JS or PHP. If you face any problem in following this, kindly do let me know.

Here is the complete code of all files:

index.html

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" />
<i class="fa fa-microphone" id="icon-record-audio" onclick="recordAudio()" style="cursor: pointer;"></i>

<script>

    let recorder = null

    function sendVoiceNote(base64) {
        // create an instance for AJAX
        var ajax = new XMLHttpRequest()

        // set request method as POST, set URL and set asynchronous to true
        // ajax.open("POST", "http://localhost:3000/sendVoiceNote", true)
        ajax.open("POST", "http://localhost/record-audio-from-web/sendVoiceNote.php", true)

        // whenever the status of request is changed
        // ajax.onreadystatechange = async function() {
        //     if (this.readyState == 4) {
        //         if (this.status == 200) {
        //             console.log(this.responseText)
        //         }

        //         if (this.status == 500) {
        //             console.log(this.responseText)
        //         }
        //     }
        // }

        // send base64 string to server
        const formData = new FormData()
        formData.append("base64", base64)
        ajax.send(formData)
    }

	function doRecordAudio() {
        return new Promise(function (resolve) {
            // get user audio media
            navigator.mediaDevices.getUserMedia({
                audio: true
            })
            .then(function (stream) {
                // create media recorder object
                const mediaRecorder = new MediaRecorder(stream)

                // save audio chunks in an array
                const audioChunks = []
                mediaRecorder.addEventListener("dataavailable", function (event) {
                    audioChunks.push(event.data)
                })

                // create a start function
                const start = function () {

                    // when recording starts, set the icon to stop
                    document.getElementById("icon-record-audio").className = "fa fa-stop-circle"

                    // on icon clicked
                    document.getElementById("icon-record-audio").onclick = async function() {
                        // stop the recorder
                        if (recorder != null) {
                            const audio = await recorder.stop()

                            // play the audio
                            audio.play()

                            // get audio stream
                            const reader = new FileReader()
                            reader.readAsDataURL(audio.audioBlob)
                            reader.onloadend = function() {
                                // get base64
                                let base64 = reader.result

                                // get only base64 data
                                base64 = base64.split(',')[1]

                                // send base64 to server to save
                                sendVoiceNote(base64)
                            }
                        }
                    }

                    // start media recorder
                    mediaRecorder.start()
                }

                // create a stop function
                const stop = function () {
                    return new Promise(function (resolve) {

                        // on recording stop listener
                        mediaRecorder.addEventListener("stop", function () {

                            // change the icon back to microphone
                            document.getElementById("icon-record-audio").className = "fa fa-microphone"

                            // reset the onclick listener so when again clicked, it will record a new audio
                            document.getElementById("icon-record-audio").onclick = async function() {
                                recordAudio()
                            }

                            // convert the audio chunks array into blob
                            const audioBlob = new Blob(audioChunks)

                            // create URL object from URL
                            const audioUrl = URL.createObjectURL(audioBlob)

                            // create an audio object to play
                            const audio = new Audio(audioUrl)
                            const play = function () {
                                audio.play()
                            }

                            // send the values back to the promise
                            resolve({
                                audioBlob,
                                play
                            })
                        })

                        // stop the media recorder
                        mediaRecorder.stop()
                    })
                }

                // send the values back to promise
                resolve({
                    start,
                    stop
                })
            })
        })
    }

    // function to record audio
	async function recordAudio() {
        // get permission to access microphone
		navigator.permissions.query({name: 'microphone'})
			.then(function (permissionObj) {
				console.log(permissionObj.state)				
			})
			.catch(function (error) {
				console.log('Got error :', error);
			})

        // get recorder object
		recorder = await doRecordAudio()

        // start audio
  		recorder.start()
	}
</script>

server.js

const express = require("express")
const app = express()

const expressFormidable = require("express-formidable")
app.use(expressFormidable())

const cors = require("cors")
app.use(cors())

const fileSystem = require("fs")
const http = require("http").createServer(app)

http.listen(3000, function () {
	app.post("/sendVoiceNote", async function (request, result) {
		const base64 = request.fields.base64

        const buffer = Buffer.from(base64, "base64")
        const voiceNote = "audios/" + new Date().getTime() + ".webm"
        await fileSystem.writeFileSync(voiceNote, buffer)

        result.send(voiceNote)
	})
})

sendVoiceNote.php

<?php

$base64 = $_POST["base64"];

$file_name = "audios/" . time() . ".webm";
file_put_contents($file_name, base64_decode($base64));

echo $file_name;

Gmail SMTP New Method 2023 – PHP

In this tutorial, I am going to show you, how you can use Gmail SMTP for sending emails in PHP.

Video tutorial – Gmail SMTP in PHP

I will be using PHPMailer library. You can find all the code for sending email from PHPMailer documentation.

<?php

use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\SMTP;

require 'PHPMailer/src/Exception.php';
require 'PHPMailer/src/PHPMailer.php';
require 'PHPMailer/src/SMTP.php';

//Create an instance; passing `true` enables exceptions
$mail = new PHPMailer(true);

try {
    //Server settings
    $mail->SMTPDebug = SMTP::DEBUG_SERVER;                      //Enable verbose debug output
    $mail->isSMTP();                                            //Send using SMTP
    $mail->Host       = 'smtp.gmail.com';                     //Set the SMTP server to send through
    $mail->SMTPAuth   = true;                                   //Enable SMTP authentication
    $mail->Username   = 'your_email_address@gmail.com';                     //SMTP username
    $mail->Password   = 'app_password';                               //SMTP password
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;            //Enable implicit TLS encryption
    $mail->Port       = 465;                                    //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`

    //Recipients
    $mail->setFrom('your_email_address@gmail.com', 'Your name');
    $mail->addAddress('support@adnan-tech.com', 'Adnan Tech');

    //Content
    $mail->isHTML(true);                                  //Set email format to HTML
    $mail->Subject = 'Here is the subject';
    $mail->Body    = 'This is the HTML message body <b>in bold!</b>';
    $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

    $mail->send();
    echo 'Message has been sent';
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
}

Line #18: You need to set your host to smtp.gmail.com

Line #20: Write your email address

Line #21: Write the app password you will get from your google account in the next step.

First, you need to go to your google account.

Manage google account
Manage google account

Go to security.

Security
Security

Then go to 2-step verification.

2-step verification
2-step verification

After that, go to app passwords.

App passwords
App passwords

Set whatever name you want and generate.

This will generate an app password.

App password for Gmail SMTP - PHP
App password for Gmail SMTP – PHP

You can use this in your SMTP code. Line #21 of the above code.

Make sure there is no space in password. Then try again. You should receive an email now.

Learn how to do it in Node JS from here.

If you need any help in following this, kindly do let me know.