Multi-purpose platform in Node.js and MongoDB

A multi-purpose platform is created in Node.js and MongoDB. Developing an API in Node.js and MongoDB allows you to create real-time, high performance and scalable applications. When you are building a website or a mobile app, you might have a different design than what is already built. But your backend will be almost similar to your competitor. Let’s say you want to build a social network like Facebook. You will pick an HTML template or design a UI specific for your business. But you want to have a module to create users, posts, pages, groups, friends, chats and much more.

So we are providing you a multi-purpose platform that allows you to use social network, job portal, manage your media files and much more. It is a self-hosted script so all the data will be stored on your server, no third-party storage service is used here.

Tech stack ๐Ÿ’ป

  • Bootstrap 5+
  • React 18+
  • Node.js 20+
  • MongoDB 4+

User Registration and Profile ๐Ÿ™‹๐Ÿปโ€โ™‚๏ธ

This API allows you to register an account. The passwords are encrypted before saving them in database. User can also login using his email and password that he entered during registration.

On successfull login, a Json Web Token (JWT) is generated and returned in the API response. The client application needs to save that token in its local storage because that token will be use in other APIs in headers to identify the user. This token is also stored in server as well. So if you want to logout a user manually, you can simply remove his token from database.

User can edit his name and profile image. The email field is read-only, it cannot be changed. User can also change his password. For that, he needs to provide his current password and enter his new password 2 times for confirmation.

Social Network Posts ๐Ÿ“

If you are building a social network, then this module allows you to create and manage posts for a social network. You can also share other’s posts on your timeline. You can edit or remove your own posts. Other users will be able to like, comment or share your posts. Users will be able to edit to delete their own comments. You will be able to reply to the comments on your posts, and you can also edit or remove your reply if you want. Users can also see the list of all users who has liked or shared your post.

Pages ๐Ÿ“ƒ

If you are running a business, you can create a page for your business and start posting about your products or services in that page. In order to create a page, you need to set it’s name, tell a little about the page, and provide a cover photo for the page. User can follow your page and start seeing your page’s posts in their newsfeed. Only creator of page can create a post in that page.

You can see a list of all users who has followed your page. User can also see a list of all pages he has followed. The owner of the page can edit or delete the page. Once page is deleted, all the posts inside that will be deleted as well.

Groups ๐Ÿฅณ

You can create groups to create a community of like-minded people. In order to create a group, you need to enter the name of group, a little description about the group and it’s cover photo. You can see a list of all groups created in the platform. There are separate links from where you can see only the groups that you have created or the groups you have joined. You can join or leave the group whenever you want. However, admin of the group can also remove you from the group if he wants.

Only admin or group members can post in a group. Posts uploaded by admin will be immediately displayed on the groups newsfeed. However, the posts uploaded by group members will be held pending for approval from the admin. Admin can see a list of all posts uploaded by group members. He can accept or decline a post he wants.

Admin of the group can update the name or description of the group, and he can also change the cover photo of the group. Admin can delete the group as well. Upon deleting, all the posts uploaded in that group will be deleted as well.

Media ๐Ÿ“‚

This API allows you to upload media files (images, videos) on the platform. Each media file will have a title, alt attribute, and caption. These will help you in your Search Engine Optimization (SEO). You can edit or delete your own media files whenever you want.

Friends ๐Ÿ™๐Ÿป

You can create friends by sending them a friend request, just like you do in Facebook. Other user can see a list of all friend requests he has received. He can accept or decline your request. If accepted, then you both will become friends and you can chat with each other. You can see a list of all of your friends. At any point, you can remove a user from your friend list.

Realtime Chat ๐Ÿ’ฌ

You can have realtime chat with your friends. Chats are end-to-end encrypted, that means that the messages are encrypted before sending to the server. And they are decrypted only after receiving the response from the server. Your messages will remain secure in-transit.

For realtime communication, we are using Socket IO. When you send a message, an event is emitted. The receiver will be listening to that event and display a notification alert that you have received a new message. If the chat is already opened, then the new message will automatically be appended at the bottom of the chat.

Job Portal ๐Ÿ‘จ๐Ÿปโ€๐Ÿ”ง ๐Ÿ‘จ๐Ÿปโ€๐Ÿณ ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿซ ๐Ÿ‘ฉ๐Ÿปโ€๐ŸŽจ

Since this is a multi-purpose platform and it is developed in scalable technologies (Node.js & MongoDB), a job portal platform is also added that allows recruiter to post jobs and candidates can apply on that job. Recruiter can see all the applications he has received on a job and can change the status of applicant to shortlisted, interviewing, rejected or selected etc. Candidate can upload multiple CVs and choose the relevant CV while applying for the job. Recruiter can update or delete the job any time.

You can also filter job applications by status. So if you are recruiter, you will post a job. Then you will start receiving applications from candidates. Recruiter can change the status from interviewing to shortlisted employess. Then recruiter can change the status to interviewing. Recruiter can also reject the candidate, but he also needs to provide a reason for rejection. Finally, recruiter can set the candidate as “Hired”. So there must be a way for recruiter to filter job applications by their status.

We also have a PHP and MySQL version of Job Portal website. You can get it from here.

Admin Panel ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ผ

An admin panel is created where you can manage all the users, social network posts and jobs created on the platform. It is a single page application created in React JS and can be deployed as a sub-domain to your main website.

Super admin can see the list of all users. He can add a new user if he wants. An email with password set by admin will be sent to the new user. Admin can also update the user password as well. He can also delete the user, all the posts uploaded by that user will be deleted as well.

Super admin can see all the posts uploaded on social network platform. Just like users, he can delete any post he did not feel appropriate.

Admin can also see all the jobs posted by recruiter and if any job post goes against the standards, super admin can remove it.

Blogs ๐Ÿ“œ

Since this is a multi-purpose platform, so I added a blog module that allows you to write articles on your website. Admin can create blogs from admin panel and they will be displayed on user side. User can post a comment if they are logged-in. Other users or admin can reply to their comments. Admin can manage all posts and comments from admin panel. Admin can delete any post or command he did not find suitable.

We are using sockets to update the blogs in realtime. So if user is reading a post and admin changes something from admin panel, it will immediately gets updated on user side. User does not need to refresh the page.

Page Builder ๐Ÿ—

We are using page builder to create blog posts. It allows you to create paragraphs, headings, images, videos and buttons.

You can set the attributes like id and class. You can also set CSS properties of each tag.

If you are using image or video, you can add alt and caption attributes as well.

Freelance Platform ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป ๐Ÿค‘

This multi-purpose platform project also has a freelance platform where you can hire experts to get your job done. Or, if you are a skilled person, you can find work there.

There are 2 entities in freelance platform: Buyer ๐Ÿ’ฐ and Seller ๐Ÿค‘. Buyer will create a task to be done, he will mention his budget and deadline. Buyer must have sufficient balance in their account. They can add balance using Stripe. ๐Ÿ’ณ

Sellers will start bidding on that task. Seller will also send a proposal mentioning how he will get the work done, what is his offer and in how many days he will do it. ๐ŸŒš

Buyer will see all the bids from sellers. He will also see a freelance profile of each bidder, telling the orders done by each seller, their ratings and reviews etc. โญ๏ธ

Buyer can accept the bid of any seller he seems fit for the job. The seller will be notified and their order will be started. โฐ

On their order detail page, they can chat with each other. They can send messages ๐Ÿ’ฌ with attachments ๐Ÿงท. At any point, buyer or seller can cancel the order.

After the work is done, buyer can complete the order โœ…. Once it is completed, the amount that was offered in the bid will be deducted from buyer’s account. 5 percent will be deducted as a “platform fee”, and the remaining 95% of the amount will be added in the seller’s account ๐Ÿค‘.

Buyer can also gives ratings โญ๏ธ to a seller and also can give a review about his experience. This will help seller build his freelance profile.

Seller can withdraw the money by entering his bank account details ๐Ÿฆ. These details will be sent to the admin panel ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ผ. Admin can transfer the funds and once the transfer is completed, seller’s balance will be returned to 0.

Notifications ๐Ÿ””

User will receive a notification when:

  • His freelance order gets completed/cancelled.
  • A new message has been received on his order.
  • His bid got accepted on freelance project.
  • His withdrawl request has been updated.
  • Someone commented on his post.
  • Someone replied to his comment.
  • Someone likes his post on social network.
  • His post has been shared by someone.

These notifications will be displayed as a bell icon ๐Ÿ”” on header when user is logged-in. If he has any unread notifications, then it will be displayed as read.

Unread notification’s background will be gray. On clicking the notification, it will be marked as read.

Installer ๐Ÿคน๐Ÿปโ€โ™‚๏ธ

Run the following commands in your “admin” folder:

npm install
npm start

In order to create a super admin, you need to run the following command in your “premium-api” folder once:

node installer.js

This will create a super admin in your database. You can set the email and password of your choice from “installer.js” file.

Paste the “multi-purpose-platform-nodejs-mongodb” folder in your “htdocs” folder if you are using XAMPP or MAMP, or in “www” folder if you are using WAMP.

Run the following commands in the “premium-api” folder:

npm update
npm install -g nodemon
nodemon index.js

Project can be accessed from:

http://localhost/multi-purpose-platform-nodejs-mongodb/web/index.html

Demos ๐ŸŽฏ

1. Social network – Posts

2. Pages

3. Groups

4. Friends & chat

5. Job portal

6. Admin panel

7. Blogs

8. Freelance Platform

More features can also be added on-demand in this multi-purpose platform. If you do not want all the features, we can remove or change features as per your needs.

Files included ๐Ÿ—„

  • api
    • index.js
    • installer.js
    • modules
      • admin
        • admin.js
        • auth.js
      • auth-optional.js
      • auth.js
      • freelance.js
      • banks.js
      • payments.js
      • blogs.js
      • categories.js
      • chats.js
      • files.js
      • job-portal
        • cvs.js
        • gigs.js
        • jobs.js
      • mails.js
      • media.js
      • notifications.js
      • sn
        • friends.js
        • groups.js
        • pages.js
        • posts.js
      • users.js
    • package.json
    • uploads
      • private
      • public
  • web
    • freelance
      • buyer.html
      • order-detail.html
      • orders.html
      • seller.html
      • task-detail.html
    • blogs
      • index.html
      • detail.httml
    • change-password.html
    • index.html
    • balance.html
    • withdraw.html
    • job-portal
      • applied.html
      • create.html
      • cv-manager.html
      • detail.html
      • edit.html
      • index.html
      • my.html
    • login.html
    • media
      • index.html
      • edit.html
    • profile.html
    • public
      • css
      • js
      • img
    • register.html
    • sn
      • chat.html
      • edit-comment.html
      • edit-post.html
      • edit-reply.html
      • friends.html
      • groups
        • create.html
        • detail.html
        • edit.html
        • index.html
        • members.html
        • my-joined.html
        • my.html
        • pending-posts.html
      • index.html
      • notifications.html
      • pages
        • create.html
        • detail.html
        • edit.html
        • index.html
        • followers.html
        • my-followed.html
        • my.html
      • post.html
      • profile.html
      • search.html
      • send-reply.html
  • admin (SPA)
    • package.json
    • public
    • src
      • App.css
      • App.js
      • index.js
      • components
        • blogs
          • AddPost.js
          • Comments.js
          • EditPost.js
          • Posts.js
        • categories
          • AddCategory.js
          • Categories.js
          • EditCategory.js
        • Dashboard.js
        • ecommerce
          • AddProduct.js
          • EditProduct.js
          • Orders.js
          • Products.js
        • files
          • Files.js
        • jobs
          • Jobs.js
        • layouts
          • Header.js
          • Footer.js
          • Sidebar.js
        • Login.js
        • sn
          • Posts.js
        • users
          • AddUser.js
          • EditUser.js
          • Users.js

Get auth user without sanctum middleware – Laravel

In order to get an authentication user without using sanctum middleware in Laravel, you just need to pass the string “sanctum” in auth() method.

Auth sanctum without middleware

Following route goes in the “routes/api.php” file:

# routes/api.php

Route::post("/auth-without-sanctum", function () {
    return auth("sanctum")->user();
});

Auth sanctum with middleware

If you do not want to use the “sanctum” string in auth() method, then you need to wrap your route inside sanctum middleware. Like this:

Route::group([
    "middleware" => ["auth:sanctum"]
], function () {

    Route::post("/auth-without-sanctum", function () {
        return auth()->user();
    });
    
});

Generate API Token

In order to check if the above code is working fine, we need to call an AJAX with authorization token. To create an authorization token (just for testing), we will use the following code:

# app/Http/Controllers/UserController.php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use DB;
use App\Models\User;

class UserController extends Controller
{
    public function generate_token()
    {
        $user = DB::table("users")
            ->where("email", "=", "adnan@gmail.com")
            ->first();

        if ($user == null)
        {
            $id = DB::table("users")
                ->insertGetId([
                    "name" => "Adnan",
                    "email" => "adnan@gmail.com",
                    "password" => password_hash("adnan", PASSWORD_DEFAULT),
                    "created_at" => now()->utc(),
                    "updated_at" => now()->utc()
                ]);
        }
        else
        {
            $id = $user->id;
        }

        $user = User::where("id", "=", $id)->first();

        $token = $user->createToken("adnan-tech.com")->plainTextToken;
        dd($token);
    }
}

createToken(secret_string) method accepts a secret string that will be used to generate plain text tokens. You can write any string you want. Copy the value of $token variable and use it in AJAX request later in this tutorial.

Note: If you face an error while generating a token, run the following command in your terminal:

php artisan install:api

It will ask you to add Laravel\Sanctum\HasApiTokens trait in your User model. You can add it in the following way:

# app/Models/User.php

...
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasFactory, Notifiable, HasApiTokens;
    
    ...
}

Learn more about Laravel sanctum from their official documentation.

AJAX with authorization header token

We are calling a simple AJAX request to this API route and passing the token value after “Bearer ” (notice the space).

var ajax = new XMLHttpRequest()
ajax.open("POST", "api/auth-without-sanctum", true)
ajax.setRequestHeader("Accept", "application/json")
ajax.setRequestHeader("Authorization", "Bearer 1|EovaNhClZ1DBrwEMRasAgpfZc7AqNF5yNaBGP76U1be5a11f")

ajax.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        console.log(this.responseText)
    }
}

ajax.send()

Open your browser inspect element and goto “Network” tab, you will see the user object in “Preview”.

Chrome inspect element network - Laravel get authenticated user without using sanctum middleware
Chrome inspect element network

Now try commenting out the line that sends authorization header in AJAX request. You will receive an empty or null response (make sure the API route is not wrapped in auth:sanctum middleware).

Error: Route [login] not defined

If you get an error “Route [login] not defined”.

Route [login] not defined - Laravel
Route [login] not defined – Laravel

Then it can also be fixed by adding the following 2 headers with your AJAX request.

ajax.setRequestHeader("Accept", "application/json")
ajax.setRequestHeader("Authorization", "Bearer 1|EovaNhClZ1DBrwEMRasAgpfZc7AqNF5yNaBGP76U1be5a11f")

And then set the name “login” to your login route.

// web.php

Route::get("/login", function () {
  return view("login");
})->name("login");

More

Learn how to fix 403 forbidden error on Laravel storage

This is how you can get an authenticated (auth() method) user in Laravel without using sanctum middleware.

Get user location in PHP

In this article, we will teach you, how you can get user location in PHP. We have a users table where we are saving the user’s location and the time when the last location was fetched.

CREATE TABLE users (
    id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    password VARCHAR(255) NOT NULL,
    location JSON NULL DEFAULT NULL,
    last_location_at TIMESTAMP NULL DEFAULT NULL
);

The most important columns are “location” and “last_location_at”. We will be fetching the user’s location every 24 hours. The following code will fetch the user location in PHP.

if (isset($_SERVER['HTTP_X_FORWARDED_FOR']))
{
    $client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
else if (isset($_SERVER['HTTP_X_REAL_IP']))
{
    $client_ip = $_SERVER['HTTP_X_REAL_IP'];
}
else
{
    $client_ip = $_SERVER['REMOTE_ADDR'];
}

$user_agent = $_SERVER['HTTP_USER_AGENT'];

$timestamp = strtotime($user->last_location_at);

$current_timestamp = time();

$difference = $current_timestamp - $timestamp;

$twenty_four_hours_in_seconds = 24 * 60 * 60;

if ($difference >= $twenty_four_hours_in_seconds)
{
    $curl = curl_init();
    curl_setopt_array($curl, [
        CURLOPT_URL => "http://www.geoplugin.net/json.gp?ip=" . $client_ip,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode([]),
        CURLOPT_HTTPHEADER => [
            "Content-Type: application/json"
        ]
    ]);
    $response = curl_exec($curl);

    if (curl_errno($curl))
    {
        $error = curl_error($curl);
    }
    else
    {
        $response = json_decode($response);
        if ($response->geoplugin_status == 200)
        {
            $location = [
                "city" => $response->geoplugin_city,
                "continent" => $response->geoplugin_continentName,
                "continentCode" => $response->geoplugin_continentCode,
                "country" => $response->geoplugin_countryName,
                "countryCode" => $response->geoplugin_countryCode,
                "currencyCode" => $response->geoplugin_currencyCode,
                "currencySymbol" => $response->geoplugin_currencySymbol,
                "currencyConverter" => $response->geoplugin_currencyConverter,
                "latitude" => $response->geoplugin_latitude,
                "longitude" => $response->geoplugin_longitude,
                "region" => $response->geoplugin_region,
                "ipAddress" => $response->geoplugin_request,
                "timezone" => $response->geoplugin_timezone,
                "user_agent" => $user_agent
            ];
            $location = json_encode($location);

            // UPDATE `users` SET location = '$location', last_location_at = NOW() WHERE id = 2
        }
    }
    curl_close($curl);
}

Explanation:

  • Line 01-12: We are fetching the user’s IP address. When a user accesses the web server through a proxy or load balancer, the “REMOTE_ADDR” does not provide the actual IP address, rather it provides the IP address of the load balancer. That is why we are checking if the “HTTP_X_FORWARDED_FOR” or “HTTP_X_REAL_IP” headers are present. These headers are present when the user accesses the web server via proxy or load balancer.
  • Line 14: Getting the user’s device and browser information. It will tell if the user is using Chrome, Firefox, Safari, or whatever the browser. It will also tell the operating system he is using, if it is Mac OS, Windows, or Linux.
  • Line 16: Here we are getting the timestamp since the last location was fetched of that user. You might be getting this value from the database. If it is null, then it will return the seconds since 1970, which is good in case of null.
  • Line 18: Get the current timestamp in seconds.
  • Line 20: Get the difference between 2 times.
  • Line 22: Calculate how many seconds are there in 24 hours.
  • Line 24: Check if the time has passed 24 hours.
  • After that, I am calling a GeoPlugin API and passing the client’s IP address to it. I am saving all the required fields returned from API in a variable $location and converting that to JSON string. Then you can save that $location string in your database. Make sure to update the last_location_at to the current timestamp. This will make sure that the next location will be fetched after 24 hours.

One more thing:

You can show the user location on Google Maps too. You can follow this guide.

This feature has been practically implemented in an open-source Laravel boilerplate.

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.