<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[The Pixel District]]></title><description><![CDATA[The Pixel District]]></description><link>https://blog.paulwababu.me.ke</link><generator>RSS for Node</generator><lastBuildDate>Wed, 03 Jun 2026 17:59:47 GMT</lastBuildDate><atom:link href="https://blog.paulwababu.me.ke/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Build an E-Commerce Site with Wagtail CMS,  Bootstrap & Django Framework.]]></title><description><![CDATA[In this blog, we build a fully functional e-commerce site with Django and Wagtail CMS. I will also be briefly discussing:

Why choose django framework to build a custom e-commerce website
Which One is Better For Your Website? Django CMS Vs WordPress ...]]></description><link>https://blog.paulwababu.me.ke/build-an-e-commerce-site-with-wagtail-cms-bootstrap-and-django-framework</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/build-an-e-commerce-site-with-wagtail-cms-bootstrap-and-django-framework</guid><category><![CDATA[Web Development]]></category><category><![CDATA[Python]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Django]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Sun, 06 Feb 2022 18:21:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/9tYbOIpVcn4/upload/v1643743818389/_-dqiZG6_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In this blog, we build a fully functional e-commerce site with Django and Wagtail CMS. I will also be briefly discussing:</p>
<ul>
<li>Why choose django framework to build a custom e-commerce website</li>
<li>Which One is Better For Your Website? Django CMS Vs WordPress </li>
</ul>
<p>You can check the demo of the final product at the following <a target="_blank" href="https://www.tafari-pharmacy.tk/">URL</a></p>
<h2 id="heading-why-choose-django-for-e-commerce">Why choose Django for e-commerce?</h2>
<p>First, here are some Django features to consider if you're looking for the right framework to build a shop.</p>
<p>→ Scalability</p>
<p>Django is perfect for e-commerce startups, as it's a good fit for small websites and can scale perfectly with business growth. You can rely on Django to handle hundreds/thousands of visitors at a time. It's built with independent components you can unplug or replace depending on your needs at any specific time.</p>
<p>→ Security</p>
<p>With e-commerce, you want to make sure merchants and clients alike feel safe through your shopping experience. Django prevents a whole lot of common security mistakes, often weakening traditional PHP CMSs. For instance, Django hides your site's source code from direct viewing on the web by dynamically generating web pages.</p>
<p>→ Feature-rich</p>
<p>Compared to most frameworks, Django comes with way more features out-of-the-box. It allows you to build an app right off the bat. Perfect for supporting your online store with functionalities such as user authentification, content management, or RSS feed. If something seems to be missing, you can count on Django's community and plugins ecosystem to extend your app!</p>
<p>→ SEO-friendly</p>
<p>SEO is paramount for any online business. Django advocates best practices for SEO. Human-readable URLs and sitemap features are sure to please any marketing team.</p>
<p>Oh, and also, it's fast, which is always great for both customer experience and SEO.</p>
<p>→ Reliable</p>
<p>Django makes it easy to build custom e-commerce websites. It has a modern, easy-to-use Python Web Framework that encourages rapid development and scalable architecture. Its high level abstraction make it easier to build, connect, configure, and maintain applications. In addition, Django makes it easy to add caching, secure authentication, and URL-agnostic views</p>
<h2 id="heading-which-one-is-better-for-your-e-commerce-website-django-cms-vs-wordpress">Which One is Better For Your E-commerce Website? Django CMS Vs WordPress</h2>
<p>Django database API makes it easy to work with databases. Django has a robust  and secure authentication system. Django has a built in template engine, which means that you do not need to use a separate template language. Django is a free, open source web framework to! Django also follows the DRY(Don't Repeat Yourself) principle, DRY is the principle of reducing repetition in the code, referring back to a single source—or "snippet"—of reusable code whenever you need it.
Django also removes a lot of overhead. Develiopers do not have to worry about making their programs compatible with different versions of Python, which means they can spend more time about the application. </p>
<h2 id="heading-wagtail-cms-snipcart-e-commerce">Wagtail CMS + Snipcart e-commerce</h2>
<p>Wagtail is a developer-first Django content management system. Free and open-source, the good-hearted folks at Torchbox developed it. It's elegant, flexible, and, IMHO, kicks ass.</p>
<p>In the following Wagtail tutorial, the CMS will be in charge of creating and managing products that users will then be able to buy through a shopping cart.</p>
<p>By the end of it, you'll have a solid Django-powered e-commerce site up and running.</p>
<p>Below is a screenshot of the shop we are going to build:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643933545545/MzuKKE8F1.png" alt="Screenshot from 2022-02-04 02-54-05.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643933590810/FHzLGAx9y.png" alt="bio.png" /></p>
<p>Shall we begin!</p>
<h2 id="heading-pre-requisites">Pre-requisites</h2>
<ul>
<li>A Snipcart account.</li>
</ul>
<h2 id="heading-1-creating-a-wagtail-app">1. Creating a Wagtail app</h2>
<p>Use pip, which is packaged with Python, to install Wagtail and its dependencies:</p>
<pre><code>$ python3 -m  venv venv
$ source venv/bin/activate
$ pip install wagtail requests
</code></pre><p>Open a terminal and launch a new Wagtail site:</p>
<pre><code>$ wagtail start snipcartwagtaildemo
$ cd snipcartwagtaildemo
</code></pre><p>We have an extra step to complete the Wagtail setup, and it's to install the wagtail.contrib.settings plugin that we'll require later on.</p>
<p>In your new Wagtail project, open the base.py file located in snipcartwaigtaildemo/settings folder. Then, add wagtail.contrib.settings to the INSTALLED_APPS array.</p>
<pre><code><span class="hljs-comment"># ./setting/base.py</span>
<span class="hljs-attr">INSTALLED_APPS</span> = [
    ...,
    <span class="hljs-string">'wagtail.contrib.settings'</span>
]
</code></pre><h2 id="heading-11-models-creation">1.1 Models Creation.</h2>
<p>The first thing you need to do is create your Page models. Wagtail uses these Django models to generate a page type.</p>
<p>Open the models.py file located in the home folder of your product. This is where you'll define all your custom models.</p>
<p>Create two different models:</p>
<ul>
<li>Product: defines the product you're selling.</li>
</ul>
<ul>
<li>ProductCustomField: defines a single product custom field.</li>
</ul>
<p>Let's begin by importing the required modules:</p>
<pre><code># ./home/models.py

<span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-keyword">from</span> wagtail.core.models <span class="hljs-keyword">import</span> Page

<span class="hljs-keyword">from</span> modelcluster.fields <span class="hljs-keyword">import</span> ParentalKey

<span class="hljs-keyword">from</span> wagtail.core.models <span class="hljs-keyword">import</span> Page, Orderable
<span class="hljs-keyword">from</span> wagtail.<span class="hljs-keyword">admin</span>.edit_handlers <span class="hljs-keyword">import</span> FieldPanel, MultiFieldPanel, InlinePanel
<span class="hljs-keyword">from</span> wagtail.images.edit_handlers <span class="hljs-keyword">import</span> ImageChooserPanel
<span class="hljs-keyword">from</span> wagtail.contrib.settings.models <span class="hljs-keyword">import</span> BaseSetting, register_setting
<span class="hljs-keyword">from</span> django.core.paginator <span class="hljs-keyword">import</span> EmptyPage, PageNotAnInteger, Paginator
<span class="hljs-keyword">from</span> django.<span class="hljs-keyword">template</span>.response <span class="hljs-keyword">import</span> TemplateResponse
<span class="hljs-keyword">from</span> django.core.paginator <span class="hljs-keyword">import</span> Paginator
</code></pre><p>Now add the Product model:</p>
<pre><code><span class="hljs-comment"># ./home/models.py</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>(<span class="hljs-params">Page</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_context</span>(<span class="hljs-params">self, request</span>):</span>
        context = super().get_context(request)
        fields = []
        <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> self.custom_fields.get_object_list():
            <span class="hljs-keyword">if</span> f.options:
                f.options_array = f.options.split(<span class="hljs-string">'|'</span>)
                fields.append(f)
            <span class="hljs-keyword">else</span>:
                fields.append(f)

        context[<span class="hljs-string">'custom_fields'</span>] = fields

        <span class="hljs-keyword">return</span> context
    sku = models.CharField(max_length=<span class="hljs-number">255</span>)
    short_description = models.TextField(blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    price = models.DecimalField(decimal_places=<span class="hljs-number">2</span>, max_digits=<span class="hljs-number">10</span>)
    image = models.ForeignKey(
        <span class="hljs-string">'wagtailimages.Image'</span>,
        null=<span class="hljs-literal">True</span>,
        blank=<span class="hljs-literal">True</span>,
        on_delete=models.SET_NULL,
        related_name=<span class="hljs-string">'+'</span>
    )

    content_panels = Page.content_panels + [
        FieldPanel(<span class="hljs-string">'sku'</span>),
        FieldPanel(<span class="hljs-string">'price'</span>),
        ImageChooserPanel(<span class="hljs-string">'image'</span>),
        FieldPanel(<span class="hljs-string">'short_description'</span>),
        InlinePanel(<span class="hljs-string">'custom_fields'</span>, label=<span class="hljs-string">'Custom fields'</span>),
    ]
</code></pre><p>Update the homepage class which is responsible for listing products on the homepage only. I will be listing only 6 products on the homepage. In any Wagtail Page, you can override a method name get_context. You can add the data that the view will receive in parameters</p>
<pre><code>class HomePage(Page):
    def get_context(<span class="hljs-built_in">self</span>, request):
        context <span class="hljs-operator">=</span> <span class="hljs-built_in">super</span>().get_context(request)

        context[<span class="hljs-string">'products'</span>] <span class="hljs-operator">=</span> Product.objects.child_of(<span class="hljs-built_in">self</span>).live()[:<span class="hljs-number">6</span>]

        <span class="hljs-keyword">return</span> context
</code></pre><p>And ProductCustomField:</p>
<pre><code># ./home/models.py

<span class="hljs-keyword">class</span> ProductCustomField(Orderable):
    product = ParentalKey(Product, on_delete=models.<span class="hljs-keyword">CASCADE</span>, related_name=<span class="hljs-string">'custom_fields'</span>)
    <span class="hljs-type">name</span> = models.CharField(max_length=<span class="hljs-number">255</span>)
    <span class="hljs-keyword">options</span> = models.CharField(max_length=<span class="hljs-number">500</span>, <span class="hljs-keyword">null</span>=<span class="hljs-keyword">True</span>, blank=<span class="hljs-keyword">True</span>)

    panels = [
        FieldPanel(<span class="hljs-string">'name'</span>),
        FieldPanel(<span class="hljs-string">'options'</span>)
    ]
</code></pre><p>We need to add one more view that will be responsible for showing all products in our online shop, and for paginating the page. I will be paginating on the backend side as loading all the objects on a page is not very efficient. We can however cache our data and load it all on the front end. This will make the pagination seamless, this all depends on the size of your database.</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">shop</span><span class="hljs-params">(request)</span></span>:
    products = Product.objects.live()
    p = Paginator(products, <span class="hljs-number">10</span>)
    <span class="hljs-comment">#shows number of items in page</span>
    totalProducts = (p.count)
    pageNum = request.GET.get(<span class="hljs-string">'page'</span>, <span class="hljs-number">1</span>)
    page1 = p.page(pageNum)

    <span class="hljs-keyword">return</span> TemplateResponse(request, <span class="hljs-string">'home/shop.html'</span>, {
        <span class="hljs-string">'products'</span>: products,
        <span class="hljs-string">'dataSaved'</span><span class="hljs-symbol">:page1</span>
    })
</code></pre><p>Finally, add the about us and contact us section views, like so:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">about</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">return</span> TemplateResponse(request, <span class="hljs-string">'home/about.html'</span>, {
    }) 

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">contact</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">return</span> TemplateResponse(request, <span class="hljs-string">'home/contact.html'</span>, {
    })
</code></pre><h2 id="heading-2-adding-snipcart-configuration-settings">2. Adding Snipcart configuration settings</h2>
<p>Let's make sure you can update the Snipcart API key directly from Wagtail's dashboard.</p>
<p>You'll need to add site settings to do so.</p>
<p>Site settings are special fields that you can add to your models.py file. They'll appear in the Wagtail Settings section of the dashboard.</p>
<p>Import this module:</p>
<pre><code><span class="hljs-comment"># ./home/models.py</span>

<span class="hljs-keyword">from</span> wagtail.contrib.settings.models <span class="hljs-keyword">import</span> BaseSetting, register_setting
</code></pre><p>Then add these:</p>
<pre><code><span class="hljs-comment"># ./home/models.py</span>

<span class="hljs-meta">@register_setting</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SnipcartSettings</span>(<span class="hljs-params">BaseSetting</span>):</span>
    api_key = models.CharField(
        max_length=<span class="hljs-number">255</span>,
        help_text=<span class="hljs-string">'Your Snipcart public API key'</span>
    )
</code></pre><h2 id="heading-3-database-migrations">3. Database migrations</h2>
<p>Now that your models are created, you'll need to generate database migrations and run them.</p>
<p>In your terminal, use the makemigrations command:</p>
<pre><code>$ python3 manage.py makemigrations
$ python3 manage.py migrate
</code></pre><p>Finally, create your first CMS user with the createsuperuser command:</p>
<pre><code>$ python3 manage.py createsuperuser
</code></pre><p>It will ask for an email address, a username, and to create a password. Don't forget the username and password you picked; you will need them to log into Wagtail's dashboard.</p>
<h2 id="heading-4-creating-products">4. Creating products</h2>
<p>Fire up your server like so:</p>
<pre><code>$ python3 manage.py runserver
</code></pre><p>Now open your browser and navigate to http://127.0.0.1:8000/admin. Use the credentials you set up earlier to log in.</p>
<p>Select the Home page in Wagtail's menu. Then click on the Add child page button.</p>
<p>You'll be asked to pick a type of page, select Home page and give it a name.</p>
<p>Go back to the Home page menu and click Add child page button under your newly created page.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643797512409/bVK_wRbdi7.webp" alt="1629928245-addchildproduct.webp" /></p>
<p>Once again, you'll be asked to pick a type of page, this time select Product.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643797579389/rGb3LVLia.webp" alt="1629928289-wagtailcreateproduct.webp" /></p>
<p>You can create as many products as you wish.</p>
<h2 id="heading-41-adding-snipcart-api-key">4.1 Adding Snipcart API key</h2>
<p>Remember the SnipcartSettings class you created? You'll be able to configure your API key by expanding the Settings menu and going to Snipcart settings.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643797693753/4jQpwA_Hh.webp" alt="1629928362-snipcart-setting-wagtail.webp" /></p>
<p>Open Snipcart's dashboard and get your public API key (Test or Live), go back to Wagtail, and paste it in the API key field.</p>
<p>Save your settings.</p>
<h3 id="heading-adding-new-url-routes">Adding new URL routes</h3>
<p>I have barely used wagtail and i am not very familiar with how the URL's are handled but i created my own URL for the shop view, for listing all products:</p>
<pre><code><span class="hljs-keyword">from</span> django.conf <span class="hljs-keyword">import</span> settings
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> include, path
<span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin

<span class="hljs-keyword">from</span> wagtail.admin <span class="hljs-keyword">import</span> urls <span class="hljs-keyword">as</span> wagtailadmin_urls
<span class="hljs-keyword">from</span> wagtail.core <span class="hljs-keyword">import</span> urls <span class="hljs-keyword">as</span> wagtail_urls
<span class="hljs-keyword">from</span> wagtail.documents <span class="hljs-keyword">import</span> urls <span class="hljs-keyword">as</span> wagtaildocs_urls

<span class="hljs-keyword">from</span> search <span class="hljs-keyword">import</span> views <span class="hljs-keyword">as</span> search_views
<span class="hljs-keyword">from</span> home <span class="hljs-keyword">import</span> models <span class="hljs-keyword">as</span> p
urlpatterns = [
    path(<span class="hljs-string">'django-admin/'</span>, admin.site.urls),

    path(<span class="hljs-string">'admin/'</span>, include(wagtailadmin_urls)),
    path(<span class="hljs-string">'documents/'</span>, include(wagtaildocs_urls)),

    path(<span class="hljs-string">'search/'</span>, search_views.search, name=<span class="hljs-string">'search'</span>),
    path(<span class="hljs-string">'shop/'</span>, p.shop, name=<span class="hljs-string">'shop'</span>),
    path(<span class="hljs-string">'about/'</span>, p.about, name=<span class="hljs-string">'about'</span>),
    path(<span class="hljs-string">'contact/'</span>, p.contact, name=<span class="hljs-string">'contact'</span>),

]


<span class="hljs-keyword">if</span> settings.DEBUG:
    <span class="hljs-keyword">from</span> django.conf.urls.static <span class="hljs-keyword">import</span> static
    <span class="hljs-keyword">from</span> django.contrib.staticfiles.urls <span class="hljs-keyword">import</span> staticfiles_urlpatterns

    <span class="hljs-comment"># Serve static and media files from development server</span>
    urlpatterns += staticfiles_urlpatterns()
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

urlpatterns = urlpatterns + [
    <span class="hljs-comment"># For anything not caught by a more specific rule above, hand over to</span>
    <span class="hljs-comment"># Wagtail's page serving mechanism. This should be the last pattern in</span>
    <span class="hljs-comment"># the list:</span>
    path(<span class="hljs-string">""</span>, include(wagtail_urls)),

    <span class="hljs-comment"># Alternatively, if you want Wagtail pages to be served from a subpath</span>
    <span class="hljs-comment"># of your site, rather than the site root:</span>
    <span class="hljs-comment">#    path("pages/", include(wagtail_urls)),</span>
]
</code></pre><h2 id="heading-5-templating">5. Templating</h2>
<p>Let us now proceed with creating our HTML files and modifying our application UI. The template is from this <a target="_blank" href="https://colorlib.com/wp/template/pharma/">Colorlib URL</a>.</p>
<h3 id="heading-homepage">Homepage</h3>
<p>On our homepage, we need to display a few items from our database. We already specified 6 items on our homepage view. Create 3 files on the home/templates/home folder:</p>
<ul>
<li>home_page.html</li>
<li>product.html</li>
<li>shop.html</li>
</ul>
<p>Before i display the whole code, let me explain a few important bits, starting with the head of the HTML files</p>
<pre><code>{% load static wagtailcore_tags wagtailuserbar %}
{% load wagtailimages_tags %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>

  {% load static wagtailsettings_tags %}
    {% get_settings %}

    {# Global stylesheets #}
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Rubik:400,700|Crimson+Text:400,400i"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'fonts/icomoon/style.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/bootstrap.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/magnific-popup.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/jquery-ui.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.carousel.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.theme.default.min.css' %}"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/aos.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/style.css' %}"</span>&gt;</span>

    {# Snipcart #}

    {% if settings.home.SnipcartSettings.api_key %}
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">async</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">hidden</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"snipcart"</span> <span class="hljs-attr">data-api-key</span>=<span class="hljs-string">"{{ settings.home.SnipcartSettings.api_key }}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.css"</span> /&gt;</span>
    {% endif %}

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
</code></pre><p>We have the reference for the snipcart tags where it detects the API key we added on the settings file and have reference for the snipcart files as cdn files.</p>
<pre><code><span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"row"</span><span class="hljs-operator">&gt;</span>
          {<span class="hljs-operator">%</span> <span class="hljs-keyword">for</span> product in products <span class="hljs-operator">%</span>}
          <span class="hljs-operator">&lt;</span>div class<span class="hljs-operator">=</span><span class="hljs-string">"col-sm-6 col-lg-4 text-center item mb-4"</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>a href<span class="hljs-operator">=</span><span class="hljs-string">"{{ product.get_url }}"</span><span class="hljs-operator">&gt;</span>
                {<span class="hljs-operator">%</span> image product.image fill<span class="hljs-operator">-</span>370x270 <span class="hljs-keyword">as</span> tmp_image <span class="hljs-operator">%</span>}
                <span class="hljs-operator">&lt;</span>img src<span class="hljs-operator">=</span><span class="hljs-string">"{{ tmp_image.url }}"</span> alt<span class="hljs-operator">=</span><span class="hljs-string">"Image"</span><span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>h3 class<span class="hljs-operator">=</span><span class="hljs-string">"text-dark"</span><span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span>a href<span class="hljs-operator">=</span><span class="hljs-string">"{{ product.get_url }}"</span><span class="hljs-operator">&gt;</span>{{ product.title }}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>a<span class="hljs-operator">&gt;</span><span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>h3<span class="hljs-operator">&gt;</span>
            <span class="hljs-operator">&lt;</span>p class<span class="hljs-operator">=</span><span class="hljs-string">"price"</span><span class="hljs-operator">&gt;</span>Ksh. {{ product.price }}<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>p<span class="hljs-operator">&gt;</span>
          <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
          {<span class="hljs-operator">%</span> endfor <span class="hljs-operator">%</span>}
        <span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>div<span class="hljs-operator">&gt;</span>
</code></pre><p>We also have the product part that loops through the products and displays them all. For more details, you can visit the snip cart docs.
The whole code for the homepage is:</p>
<pre><code>{% load static wagtailcore_tags wagtailuserbar %}
{% load wagtailimages_tags %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>

  {% load static wagtailsettings_tags %}
    {% get_settings %}

    {# Global stylesheets #}
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Rubik:400,700|Crimson+Text:400,400i"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'fonts/icomoon/style.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/bootstrap.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/magnific-popup.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/jquery-ui.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.carousel.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.theme.default.min.css' %}"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/aos.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/style.css' %}"</span>&gt;</span>

    {# Snipcart #}

    {% if settings.home.SnipcartSettings.api_key %}
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">async</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">hidden</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"snipcart"</span> <span class="hljs-attr">data-api-key</span>=<span class="hljs-string">"{{ settings.home.SnipcartSettings.api_key }}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.css"</span> /&gt;</span>
    {% endif %}

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {% wagtailuserbar %}
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-wrap"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navbar py-2"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-wrap"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-close js-search-close"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-close2"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search keyword and hit enter..."</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-flex align-items-center justify-content-between"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-logo"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"js-logo-clone"</span>&gt;</span>Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-nav d-none d-lg-block"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navigation text-right text-md-center"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu js-clone-nav d-none d-lg-block"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"active"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                {% if request.path == '/' %}
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/shop"</span>&gt;</span>Store<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                {% endif %}
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Medications<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

                  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block js-search-open"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-search"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block bag"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout icon-shopping-bag"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout number snipcart-items-count"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu-toggle js-menu-toggle ml-3 d-inline-block d-lg-none"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-menu"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-blocks-cover"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/hero_1.jpg' %}');"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-7 mx-auto order-lg-2 align-self-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-block-cover-content text-center"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sub-title"</span>&gt;</span>Effective Medicine, New Medicine Everyday<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Welcome To Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                {% if request.path == '/' %}
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary px-5 py-3"</span>&gt;</span>Shop Now<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                {% endif %}
              <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row align-items-stretch section-overlap"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-4 mb-4 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-wrap bg-primary h-100"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h5</span>&gt;</span>Free <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span> Delivery<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                  Amet sit amet dolor
                  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing.<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-4 mb-4 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-wrap h-100"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h5</span>&gt;</span>Season <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span> Sale 50% Off<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                  Amet sit amet dolor
                  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing.<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-4 mb-4 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-wrap bg-warning h-100"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"h-100"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h5</span>&gt;</span>Buy <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span> A Gift Card<span class="hljs-tag">&lt;/<span class="hljs-name">h5</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                  Amet sit amet dolor
                  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing.<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title-section text-center col-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-uppercase"</span>&gt;</span>Popular Products<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          {% for product in products %}
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-6 col-lg-4 text-center item mb-4"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ product.get_url }}"</span>&gt;</span>
                {% image product.image fill-370x270 as tmp_image %}
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ tmp_image.url }}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ product.get_url }}"</span>&gt;</span>{{ product.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>Ksh. {{ product.price }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          {% endfor %}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row mt-5"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-12 text-center"</span>&gt;</span>
            {% if request.path == '/' %}
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/shop"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary px-4 py-3"</span>&gt;</span>View All Products<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            {% endif %}
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section bg-light"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title-section text-center col-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-uppercase"</span>&gt;</span>New Products<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12 block-3 products-wrap"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nonloop-block-3 owl-carousel"</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center item mb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/product_03.png' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span>Umcka Cold Care<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>$120.00<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center item mb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/product_01.png' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span>Umcka Cold Care<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>$120.00<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center item mb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/product_02.png' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span>Umcka Cold Care<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>$120.00<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center item mb-4"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/product_04.png' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"shop-single.html"</span>&gt;</span>Umcka Cold Care<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>$120.00<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"title-section text-center col-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-uppercase"</span>&gt;</span>Testimonials<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12 block-3 products-wrap"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nonloop-block-3 no-direction owl-carousel"</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"testimony"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">blockquote</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/person_1.jpg' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid w-25 mb-4 rounded-circle"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;ldquo;</span>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nemo omnis voluptatem consectetur quam tempore obcaecati maiores voluptate aspernatur iusto eveniet, placeat ab quod tenetur ducimus. Minus ratione sit quaerat unde.<span class="hljs-symbol">&amp;rdquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">blockquote</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;mdash;</span> Kelly Holmes<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"testimony"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">blockquote</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/person_2.jpg' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid w-25 mb-4 rounded-circle"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;ldquo;</span>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nemo omnis voluptatem consectetur quam tempore
                    obcaecati maiores voluptate aspernatur iusto eveniet, placeat ab quod tenetur ducimus. Minus ratione sit quaerat
                    unde.<span class="hljs-symbol">&amp;rdquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">blockquote</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;mdash;</span> Rebecca Morando<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"testimony"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">blockquote</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/person_3.jpg' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid w-25 mb-4 rounded-circle"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;ldquo;</span>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nemo omnis voluptatem consectetur quam tempore
                    obcaecati maiores voluptate aspernatur iusto eveniet, placeat ab quod tenetur ducimus. Minus ratione sit quaerat
                    unde.<span class="hljs-symbol">&amp;rdquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">blockquote</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;mdash;</span> Lucas Gallone<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"testimony"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">blockquote</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'images/person_4.jpg' %}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid w-25 mb-4 rounded-circle"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;ldquo;</span>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Nemo omnis voluptatem consectetur quam tempore
                    obcaecati maiores voluptate aspernatur iusto eveniet, placeat ab quod tenetur ducimus. Minus ratione sit quaerat
                    unde.<span class="hljs-symbol">&amp;rdquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">blockquote</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-symbol">&amp;mdash;</span> Andrew Neel<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section bg-secondary bg-image"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_2.jpg' %}');"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row align-items-stretch"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_1.jpg' %}');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Tafari Pharmacy Products<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_2.jpg' %}');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner ml-auto  align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Rated by Experts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-footer"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3 mb-4 mb-lg-0"</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-7"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius quae reiciendis distinctio voluptates
                sed dolorum excepturi iure eaque, aut unde.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-3 mx-auto mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Quick Links<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-5 mb-5"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Contact Info<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address"</span>&gt;</span>203 Fake St. Mountain View, San Francisco, California, USA<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"phone"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"tel://23923929210"</span>&gt;</span>+2 392 3929 210<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"email"</span>&gt;</span>emailaddress@domain.com<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row pt-5 mt-5 text-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
              Copyright <span class="hljs-symbol">&amp;copy;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-built_in">document</span>.write(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear());</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> All rights reserved | This template is made
              with <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> by <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://colorlib.com"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"text-primary"</span>&gt;</span>Colorlib<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-3.3.1.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-ui.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/popper.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/bootstrap.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/owl.carousel.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery.magnific-popup.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/aos.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/main.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><h3 id="heading-all-products-page">All Products Page</h3>
<p>On the product.html, add the lines of code below. I didn't use the inbuilt django templates functionality to work in components so we have to repeat the tags we added in the homepage file, for every page we create. Copy paste the code below on the templates/home/shop.html:</p>
<pre><code>{% load static wagtailcore_tags wagtailuserbar %}
{% load wagtailimages_tags %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tafari Tafari Pharmacycy <span class="hljs-symbol">&amp;mdash;</span> Colorlib Template<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>

  {% load static wagtailsettings_tags %}
    {% get_settings %}

    {# Global stylesheets #}
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Rubik:400,700|Crimson+Text:400,400i"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'fonts/icomoon/style.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/bootstrap.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/magnific-popup.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/jquery-ui.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.carousel.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.theme.default.min.css' %}"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/aos.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/style.css' %}"</span>&gt;</span>

    {# Snipcart #}

    {% if settings.home.SnipcartSettings.api_key %}
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">async</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">hidden</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"snipcart"</span> <span class="hljs-attr">data-api-key</span>=<span class="hljs-string">"{{ settings.home.SnipcartSettings.api_key }}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.css"</span> /&gt;</span>
    {% endif %}

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {% wagtailuserbar %}

  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-wrap"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navbar py-2"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-wrap"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-close js-search-close"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-close2"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search keyword and hit enter..."</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-flex align-items-center justify-content-between"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-logo"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"js-logo-clone"</span>&gt;</span>Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-nav d-none d-lg-block"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navigation text-right text-md-center"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu js-clone-nav d-none d-lg-block"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"active"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/shop"</span>&gt;</span>Store<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Medications<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

                    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block js-search-open"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-search"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block bag"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout icon-shopping-bag"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout number snipcart-items-count"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu-toggle js-menu-toggle ml-3 d-inline-block d-lg-none"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-menu"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light py-3"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12 mb-0"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mx-2 mb-0"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-black"</span>&gt;</span>Store<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>



        {% for product in dataSaved.object_list %}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-6 col-lg-4 text-center item mb-4"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ product.get_url }}"</span>&gt;</span>
                {% image product.image fill-370x270 as tmp_image %}
                <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ tmp_image.url }}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-dark"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ product.get_url }}"</span>&gt;</span>{{ product.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"price"</span>&gt;</span>Ksh. {{ product.price }}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        {% endfor %}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row mt-5"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12 text-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-block-27"</span>&gt;</span>
                {% if dataSaved.has_other_pages %}
                <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pagination justify-content-center"</span>&gt;</span>
                    {% if dataSaved.has_previous %}
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"?page={{ dataSaved.previous_page_number }}"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"-1"</span>&gt;</span>Previous<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  {% endif %}

                  {% for i in dataSaved.paginator.page_range %}
                     {% if dataSaved.number == i %}
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item active"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>{{ i }}<span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sr-only"</span>&gt;</span>(current)<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                   <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  {% endif %}
                  {% endfor %} 
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item"</span>&gt;</span>
                    {% if dataSaved.has_next %}
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"?page={{ dataSaved.next_page_number }}"</span>&gt;</span>Next<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                    {% endif %}
                  <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                {% endif %}
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section bg-secondary bg-image"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_2.jpg' %}');"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row align-items-stretch"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_1.jpg' %}');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Tafari Pharmacy Products<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('{% static 'images/bg_2.jpg' %}');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner ml-auto  align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Rated by Experts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-footer"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3 mb-4 mb-lg-0"</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-7"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius quae reiciendis distinctio voluptates
                sed dolorum excepturi iure eaque, aut unde.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-3 mx-auto mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Quick Links<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-5 mb-5"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Contact Info<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address"</span>&gt;</span>203 Fake St. Mountain View, San Francisco, California, USA<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"phone"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"tel://23923929210"</span>&gt;</span>+2 392 3929 210<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"email"</span>&gt;</span>emailaddress@domain.com<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row pt-5 mt-5 text-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
              Copyright <span class="hljs-symbol">&amp;copy;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-built_in">document</span>.write(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear());</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> All rights reserved | This template is made
              with <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> by <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://colorlib.com"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"text-primary"</span>&gt;</span>Colorlib<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-3.3.1.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-ui.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/popper.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/bootstrap.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/owl.carousel.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery.magnific-popup.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/aos.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/main.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.custom-field-select'</span>).onchange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
            <span class="hljs-keyword">if</span> (event.target.dataset.field) {
                <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.snipcart-add-item'</span>)
                    .dataset[<span class="hljs-string">'itemCustom'</span> + event.target.dataset.field + <span class="hljs-string">'Value'</span>] = event.target.value;
            }
        };
    },<span class="hljs-literal">false</span>);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>The code is the same as the home page code, the only difference is in the shop.html file, we paginate our webpage, and display all products instead of just 6 like in the homepage.</p>
<h3 id="heading-product-details-and-cart-display-page">Product details and cart display page</h3>
<p>For the products page, we need to display the product when a user clicks on an item, like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644170364196/hY3yRyfeb.png" alt="Screenshot from 2022-02-06 20-58-59.png" /></p>
<p>In order to do this, we need to create a template that will be associated with the Product page model. On the product.html in the home/templates/home folder, add:</p>
<pre><code>{% load static wagtailcore_tags wagtailuserbar %}
{% load wagtailimages_tags %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Tafari Pharmacy <span class="hljs-symbol">&amp;mdash;</span> Colorlib Template<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>

  {% load static wagtailsettings_tags %}
    {% get_settings %}

    {# Global stylesheets #}
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css?family=Rubik:400,700|Crimson+Text:400,400i"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'fonts/icomoon/style.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/bootstrap.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/magnific-popup.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/jquery-ui.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.carousel.min.css' %}"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/owl.theme.default.min.css' %}"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/aos.css' %}"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{% static 'css/style.css' %}"</span>&gt;</span>

    {# Snipcart #}

    {% if settings.home.SnipcartSettings.api_key %}
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">async</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">hidden</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"snipcart"</span> <span class="hljs-attr">data-api-key</span>=<span class="hljs-string">"{{ settings.home.SnipcartSettings.api_key }}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.snipcart.com/themes/v3.2.1/default/snipcart.css"</span> /&gt;</span>
    {% endif %}

<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    {% wagtailuserbar %}
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-wrap"</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navbar py-2"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-wrap"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"search-close js-search-close"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-close2"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"post"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search keyword and hit enter..."</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-flex align-items-center justify-content-between"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"logo"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-logo"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"js-logo-clone"</span>&gt;</span>Tafari Pharmacy<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-nav d-none d-lg-block"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-navigation text-right text-md-center"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"navigation"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu js-clone-nav d-none d-lg-block"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"active"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/shop"</span>&gt;</span>Store<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Medications<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"has-children"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"dropdown"</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

                    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/about"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/contact"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block js-search-open"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-search"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icons-btn d-inline-block bag"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout icon-shopping-bag"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-checkout number snipcart-items-count"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-menu-toggle js-menu-toggle ml-3 d-inline-block d-lg-none"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-menu"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light py-3"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12 mb-0"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mx-2 mb-0"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">a</span>
              <span class="hljs-attr">href</span>=<span class="hljs-string">"/shop"</span>&gt;</span>Store<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mx-2 mb-0"</span>&gt;</span>/<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-black"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-5 mr-auto"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"border text-center"</span>&gt;</span>
                {% image page.image max-370x270 as temp_image %}
              <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{{ temp_image.url }}"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Image"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid p-5"</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h2</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-black"</span>&gt;</span>{{ page.title }}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{{page.short_description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>


            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">del</span>&gt;</span>$95.00<span class="hljs-tag">&lt;/<span class="hljs-name">del</span>&gt;</span>  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-primary h4"</span>&gt;</span>Ksh. {{ page.price }}<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
                {% for f in custom_fields %}
                    {% if f.options_array|length &gt; 0 %}
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-label"</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"{{ f.name|lower }}"</span>&gt;</span>
                                {{ f.name }}:
                            <span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-select custom-field-select"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"{{ f.name|lower }}"</span> <span class="hljs-attr">data-field</span>=<span class="hljs-string">"{{ forloop.counter }}"</span>&gt;</span>
                                {% for opt in f.options_array %}
                                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span>&gt;</span>
                                        {{ opt }}
                                    <span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                                {% endfor %}
                            <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    {% endif %}
                {% endfor %}
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>


            <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"snipcart-add-item btn btn-primary mt-6 py-2 px-4 bg-gradient-to-r from-green-400 to-blue-500 hover:from-pink-500 hover:to-yellow-500 text-white font-bold rounded-full shadow-offset hover:shadow-lg transition duration-300"</span>
                <span class="hljs-attr">data-item-name</span>=<span class="hljs-string">"{{ page.title }}"</span>
                    <span class="hljs-attr">data-item-id</span>=<span class="hljs-string">"{{ page.sku }}"</span>
                    <span class="hljs-attr">data-item-url</span>=<span class="hljs-string">"{{ page.get_full_url }}"</span>
                    <span class="hljs-attr">data-item-price</span>=<span class="hljs-string">"{{ page.price }}"</span>
                    <span class="hljs-attr">data-item-description</span>=<span class="hljs-string">"{{ page.short_description}}"</span>
                    <span class="hljs-attr">data-item-image</span>=<span class="hljs-string">"{{ temp_image.url }}"</span>
                    {% <span class="hljs-attr">for</span> <span class="hljs-attr">f</span> <span class="hljs-attr">in</span> <span class="hljs-attr">custom_fields</span> %}
                        <span class="hljs-attr">data-item-custom</span>{{<span class="hljs-attr">forloop.counter</span>}}<span class="hljs-attr">-name</span>=<span class="hljs-string">"{{f.name}}"</span>
                        <span class="hljs-attr">data-item-custom</span>{{<span class="hljs-attr">forloop.counter</span>}}<span class="hljs-attr">-options</span>=<span class="hljs-string">"{{f.options}}"</span>
                    {% <span class="hljs-attr">endfor</span> %}&gt;</span>Add to cart
            <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>


            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mt-5"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav nav-pills mb-3 custom-pill"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-tab"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"tablist"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-item"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link active"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-home-tab"</span> <span class="hljs-attr">data-toggle</span>=<span class="hljs-string">"pill"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#pills-home"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"tab"</span>
                    <span class="hljs-attr">aria-controls</span>=<span class="hljs-string">"pills-home"</span> <span class="hljs-attr">aria-selected</span>=<span class="hljs-string">"true"</span>&gt;</span>Ordering Information<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-item"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-profile-tab"</span> <span class="hljs-attr">data-toggle</span>=<span class="hljs-string">"pill"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#pills-profile"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"tab"</span>
                    <span class="hljs-attr">aria-controls</span>=<span class="hljs-string">"pills-profile"</span> <span class="hljs-attr">aria-selected</span>=<span class="hljs-string">"false"</span>&gt;</span>Specifications<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"tab-content"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-tabContent"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"tab-pane fade show active"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-home"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"tabpanel"</span> <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"pills-home-tab"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table custom-table"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Material<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Description<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Packaging<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"row"</span>&gt;</span>OTC022401<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Pain Management: Acetaminophen PM Extra-Strength Caplets, 500 mg, 100/Bottle<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>1 BT<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"row"</span>&gt;</span>OTC022401<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Pain Management: Acetaminophen PM Extra-Strength Caplets, 500 mg, 100/Bottle<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>144/CS<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">th</span> <span class="hljs-attr">scope</span>=<span class="hljs-string">"row"</span>&gt;</span>OTC022401<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Pain Management: Acetaminophen PM Extra-Strength Caplets, 500 mg, 100/Bottle<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>1 EA<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>

                    <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"tab-pane fade"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"pills-profile"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"tabpanel"</span> <span class="hljs-attr">aria-labelledby</span>=<span class="hljs-string">"pills-profile-tab"</span>&gt;</span>

                  <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table custom-table"</span>&gt;</span>

                    <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>HPIS CODE<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light"</span>&gt;</span>999_200_40_0<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>HEALTHCARE PROVIDERS ONLY<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light"</span>&gt;</span>No<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>LATEX FREE<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light"</span>&gt;</span>Yes, No<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>MEDICATION ROUTE<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">td</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"bg-light"</span>&gt;</span>Topical<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>

                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-section bg-secondary bg-image"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('images/bg_2.jpg');"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row align-items-stretch"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('images/bg_1.jpg');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Tafari Pharmacy Products<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1 h-100 d-flex"</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"background-image: url('images/bg_2.jpg');"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"banner-1-inner ml-auto  align-self-center"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>Rated by Experts<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Molestiae ex ad minus rem odio voluptatem.
                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"site-footer"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3 mb-4 mb-lg-0"</span>&gt;</span>

            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-7"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>About Us<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eius quae reiciendis distinctio voluptates
                sed dolorum excepturi iure eaque, aut unde.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-3 mx-auto mb-5 mb-lg-0"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Quick Links<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Supplements<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Vitamins<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Diet <span class="hljs-symbol">&amp;amp;</span> Nutrition<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Tea <span class="hljs-symbol">&amp;amp;</span> Coffee<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6 col-lg-3"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"block-5 mb-5"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"footer-heading mb-4"</span>&gt;</span>Contact Info<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"address"</span>&gt;</span>203 Fake St. Mountain View, San Francisco, California, USA<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"phone"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"tel://23923929210"</span>&gt;</span>+2 392 3929 210<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"email"</span>&gt;</span>emailaddress@domain.com<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row pt-5 mt-5 text-center"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-12"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
              Copyright <span class="hljs-symbol">&amp;copy;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"><span class="hljs-built_in">document</span>.write(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>().getFullYear());</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> All rights reserved | This template is made
              with <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"icon-heart"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> by <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://colorlib.com"</span> <span class="hljs-attr">target</span>=<span class="hljs-string">"_blank"</span>
                <span class="hljs-attr">class</span>=<span class="hljs-string">"text-primary"</span>&gt;</span>Colorlib<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
              <span class="hljs-comment">&lt;!-- Link back to Colorlib can't be removed. Template is licensed under CC BY 3.0. --&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-3.3.1.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery-ui.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/popper.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/bootstrap.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/owl.carousel.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/jquery.magnific-popup.min.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/aos.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"{% static 'js/main.js' %}"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-built_in">document</span>.addEventListener(<span class="hljs-string">'DOMContentLoaded'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.custom-field-select'</span>).onchange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) </span>{
            <span class="hljs-keyword">if</span> (event.target.dataset.field) {
                <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.snipcart-add-item'</span>)
                    .dataset[<span class="hljs-string">'itemCustom'</span> + event.target.dataset.field + <span class="hljs-string">'Value'</span>] = event.target.value;
            }
        };
    },<span class="hljs-literal">false</span>);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>The javascript included above is responsible for updating the Snipcart buy button when a custom field selection is made on the page. This code updates the button data attributes when the select value changes.</p>
<h2 id="heading-live-demo">Live demo</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644170643884/fGxXtUlp_.png" alt="home.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644170749018/j31GfsQGS.png" alt="Screenshot from 2022-02-06 21-04-50.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644170762836/9w6bMywtF.png" alt="Screenshot from 2022-02-06 21-05-29.png" /></p>
<p>See the <a target="_blank" href="https://www.tafari-pharmacy.tk/">live demo</a></p>
<h2 id="heading-final-thoughts-about-the-project">Final thoughts about the project</h2>
<p>Wagtail is simple, intuitive and minimal. I think wagtail is a great headless CMS, and I have enjoyed my little venture with Django, Wagtail CMS, and Bootstrap. LEt me know what you think about Wagtail in the comment section!</p>
]]></content:encoded></item><item><title><![CDATA[Personality Prediction Using K-Means Clustering Algorithm and Django Rest Framework (Article  Partly Written By GPT3)]]></title><description><![CDATA[Introduction
Artificial Intelligence is revolutionizing the world today as we know it through technical transformations. Machine learning applications are applied in our day-to-day lives, and one of the incredible applications of machine learning is ...]]></description><link>https://blog.paulwababu.me.ke/personality-prediction-using-k-means-clustering-algorithm-and-django-rest-framework-article-partly-written-by-gpt3</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/personality-prediction-using-k-means-clustering-algorithm-and-django-rest-framework-article-partly-written-by-gpt3</guid><category><![CDATA[Python]]></category><category><![CDATA[Django]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[GPT 3]]></category><category><![CDATA[Artificial Intelligence]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Wed, 26 Jan 2022 11:28:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1643056229070/YUbsbFC4H.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Artificial Intelligence is revolutionizing the world today as we know it through technical transformations. Machine learning applications are applied in our day-to-day lives, and one of the incredible applications of machine learning is to classify individuals based on their personality traits. Each person on this planet is unique and carries a unique personality. The availability of a high-dimensional and large amount of data has paved the way for increasing marketing campaigns' effectiveness by targeting specific people. Such personality-based communications are highly effective in increasing the popularity and attractiveness of products and services.</p>
<p>In this article, we build a model to predict personality based on 50 questions and deploy the model using Django Rest Framework. </p>
<p>I will also be sharing a snapshot of my code on how I was able to use GPT3 to help me generate content in this article. Every text below, except 'the steps to implement' section, was generated by <a target="_blank" href="https://www.techtarget.com/searchenterpriseai/definition/GPT-3">GPT3</a>, a natural-language processing system that can generate tweets, pens poetry, summarizes emails, answers trivia questions, translates languages and even write its own computer programs.</p>
<h2 id="heading-k-means-clustering-algorithm">K-means Clustering Algorithm.</h2>
<p>The K-Means clustering algorithm is an algorithm that is used in unsupervised machine learning. To put it simply, it is a clustering algorithm where it groups the data into clusters and then assigns a label to each of the clusters. The K-Means algorithm is an iterative algorithm, it means that it repeats the following steps in a loop until the algorithm is satisfied.</p>
<ul>
<li>Assign the input data to K clusters (there are K clusters, the algorithm sorts the data into K clusters)</li>
<li>Assign each input data to the closest cluster (the algorithm calculates the distance between the data and each of the clusters and then assigns each data to the closest cluster)</li>
<li>Update the cluster centroids (this is the average of all the data in the cluster)</li>
</ul>
<h2 id="heading-applications-of-k-means-algorithm">Applications of K-means Algorithm.</h2>
<p>The k-means clustering algorithm is used in a variety of applications. It is used in marketing, advertisement, market segmentation, and customer segmentation. It is also used in various scientific fields, like in determining someones personality.nIn determining someones personality.</p>
<h2 id="heading-five-personality-traits-ocean">Five Personality Traits (OCEAN)</h2>
<p>The big five personality traits are:</p>
<ul>
<li>Openness to experience </li>
<li>Conscientiousness </li>
<li>Extraversion </li>
<li>Agreeableness </li>
<li>Neuroticism. </li>
</ul>
<p>These are the five traits that human behavior is divided into. People can score between 1 and 5 in each of the five traits. For example, let's say that someone scores 3 in openness to experience. This means that he/she is not very open to new experiences, he/she is a person that is very comfortable with their own ways and he/she wants to stick to it. He/she is not very open to new things and he/she tries to avoid it. He/she is a person that doesn't like to try new things. For example, in a party, he/she is not very social and he/she doesn't like to talk a lot. He/she is a person that speaks little and he/she is a person that is not very sociable. In a party, he/she likes to stay at the corner and he/she won't go talk to other people. He/she will just stay and look at other people in the party. This is his/her personality. </p>
<p>Now that we have a basic understanding of the k-means algorithm and the big five personality traits, let us dive deep into building the Big Five personality traits.</p>
<h2 id="heading-steps-to-implement">Steps to implement.</h2>
<p>Let us start by building and saving our model that will be later used to make predictions for our API.</p>
<h2 id="heading-dataset">Dataset.</h2>
<p>Our dataset consists of 1,015,342 questionnaire answers collected online by <a target="_blank" href="https://openpsychometrics.org/tests/IPIP-BFFM/">Open Psychometrics</a>. Let's look at how the dataset actually appears. The dataset and entire code for this blog can be found on my <a target="_blank" href="https://github.com/paulwababu/personality-test-model">Github Repo</a> </p>
<p>We first import the necessary dependencies. If you do not have the libraries installed, kindly do so before proceeding.</p>
<pre><code><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np 
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> sklearn.<span class="hljs-keyword">cluster</span> <span class="hljs-keyword">import</span> KMeans
<span class="hljs-keyword">from</span> yellowbrick.<span class="hljs-keyword">cluster</span> <span class="hljs-keyword">import</span> KElbowVisualizer
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> MinMaxScaler
<span class="hljs-keyword">from</span> sklearn.decomposition <span class="hljs-keyword">import</span> PCA
<span class="hljs-keyword">import</span> joblib
</code></pre><p>Next, we load the dataset using pandas and then we display the number of participants:</p>
<pre><code>data_raw <span class="hljs-operator">=</span> pd.read_csv(<span class="hljs-string">'data-final.csv'</span>, sep<span class="hljs-operator">=</span><span class="hljs-string">'\t'</span>)
data <span class="hljs-operator">=</span> data_raw.copy()
pd.options.display.max_columns <span class="hljs-operator">=</span> <span class="hljs-number">150</span>

data.drop(data.columns[<span class="hljs-number">50</span>:<span class="hljs-number">107</span>], axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>, inplace<span class="hljs-operator">=</span>True)
data.drop(data.columns[<span class="hljs-number">51</span>:], axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>, inplace<span class="hljs-operator">=</span>True)

print(<span class="hljs-string">'Number of participants: '</span>, len(data))
data.head()
</code></pre><pre><code><span class="hljs-attr">Number of participants:</span>  <span class="hljs-number">1015341</span>
</code></pre><h2 id="heading-exploration-of-dataset">Exploration of Dataset.</h2>
<p>Let us begin by checking for missing values and removing the missing values, like so:</p>
<pre><code>print(<span class="hljs-string">'Missing value? '</span>, data.isnull().values.any())
print(<span class="hljs-string">'How many? '</span>, data.isnull().values.sum())
data.dropna(inplace<span class="hljs-operator">=</span>True)
print(<span class="hljs-string">'Number of participants after eliminating missing values: '</span>, len(data))
</code></pre><pre><code><span class="hljs-keyword">Is</span> there <span class="hljs-keyword">any</span> missing <span class="hljs-keyword">value</span>?  <span class="hljs-keyword">True</span>
How many missing <span class="hljs-keyword">values</span>?  <span class="hljs-number">89227</span>
Number <span class="hljs-keyword">of</span> participants <span class="hljs-keyword">after</span> eliminating missing <span class="hljs-keyword">values</span>:  <span class="hljs-number">1013481</span>
</code></pre><p>Let us now look at the participant distribution per nationality, by entering the code:</p>
<pre><code><span class="hljs-comment"># Participants' nationality distriution</span>
<span class="hljs-attribute">countries</span> = pd.DataFrame(data['country'].value_counts())
<span class="hljs-attribute">countries_5000</span> = countries[countries['country'] &gt;= <span class="hljs-number">5000</span>]
<span class="hljs-attribute">plt</span>.figure(figsize=(<span class="hljs-number">15</span>,<span class="hljs-number">5</span>))
<span class="hljs-attribute">sns</span>.barplot(data=countries_<span class="hljs-number">5000</span>, x=countries_<span class="hljs-number">5000</span>.index, y='country')
<span class="hljs-attribute">plt</span>.title('Countries With More Than <span class="hljs-number">5000</span> Participants')
<span class="hljs-attribute">plt</span>.ylabel('Participants');
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643189516648/gV6nwVEoE.png" alt="__results___6_0.png" /></p>
<p>Let us now visualize the question and answer distribution of the questionnaires, like so:</p>
<pre><code><span class="hljs-comment"># Defining a function to visualize the questions and answers distribution</span>
<span class="hljs-attribute">def</span> vis_questions(groupname, questions, color):
    <span class="hljs-attribute">plt</span>.figure(figsize=(<span class="hljs-number">40</span>,<span class="hljs-number">60</span>))
    <span class="hljs-attribute">for</span> i in range(<span class="hljs-number">1</span>, <span class="hljs-number">11</span>):
        <span class="hljs-attribute">plt</span>.subplot(<span class="hljs-number">10</span>,<span class="hljs-number">5</span>,i)
        <span class="hljs-attribute">plt</span>.hist(data[groupname[i-<span class="hljs-number">1</span>]], bins=<span class="hljs-number">14</span>, color= color, alpha=.<span class="hljs-number">5</span>)
        <span class="hljs-attribute">plt</span>.title(questions[groupname[i-<span class="hljs-number">1</span>]], fontsize=<span class="hljs-number">18</span>)
</code></pre><h3 id="heading-qandampas-related-to-extroversion-personality">Q&amp;As Related to Extroversion Personality</h3>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-string">'Q&amp;As Related to Extroversion Personality'</span>)
<span class="hljs-selector-tag">vis_questions</span>(EXT, ext_questions, <span class="hljs-string">'orange'</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643189686856/3dOqPXjOZ.png" alt="et.png" /></p>
<h3 id="heading-qandampas-related-to-neuroticism-personality">Q&amp;As Related to Neuroticism Personality</h3>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-string">'Q&amp;As Related to Neuroticism Personality'</span>)
<span class="hljs-selector-tag">vis_questions</span>(EST, est_questions, <span class="hljs-string">'pink'</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643189805228/XH_X6SgKa.png" alt="__results___10_1.png" /></p>
<h3 id="heading-qandampas-related-to-agreeable-personality">Q&amp;As Related to Agreeable Personality</h3>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-string">'Q&amp;As Related to Agreeable Personality'</span>)
<span class="hljs-selector-tag">vis_questions</span>(AGR, agr_questions, <span class="hljs-string">'red'</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643189901156/V7rzwITCk.png" alt="__results___11_1.png" /></p>
<h3 id="heading-qandampas-related-to-conscientious-personality">Q&amp;As Related to Conscientious Personality</h3>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-string">'Q&amp;As Related to Conscientious Personality'</span>)
<span class="hljs-selector-tag">vis_questions</span>(CSN, csn_questions, <span class="hljs-string">'purple'</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643190105307/JDNh5bggo.png" alt="__results___12_1.png" /></p>
<h3 id="heading-qandampas-related-to-open-personality">Q&amp;As Related to Open Personality</h3>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-string">'Q&amp;As Related to Open Personality'</span>)
<span class="hljs-selector-tag">vis_questions</span>(OPN, opn_questions, <span class="hljs-string">'blue'</span>)
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643190178703/-g3W0p-dZ.png" alt="__results___13_1.png" /></p>
<h2 id="heading-building-the-model">Building the Model</h2>
<p>We already know the number of clusters that will be present in our model, that is 5, the big five of personality traits. Let us see how we can get this value using code. For ease of calculation, we shall scale all the values between 0-1 and use only a sample of 5000, like so:</p>
<pre><code>df <span class="hljs-operator">=</span> data.drop(<span class="hljs-string">'country'</span>, axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)
columns <span class="hljs-operator">=</span> list(df.columns)

scaler <span class="hljs-operator">=</span> MinMaxScaler(feature_range<span class="hljs-operator">=</span>(<span class="hljs-number">0</span>,<span class="hljs-number">1</span>))
df <span class="hljs-operator">=</span> scaler.fit_transform(df)
df <span class="hljs-operator">=</span> pd.DataFrame(df, columns<span class="hljs-operator">=</span>columns)
df_sample <span class="hljs-operator">=</span> df[:<span class="hljs-number">5000</span>]
</code></pre><p>Let us now visualize our elbow curve. In cluster analysis, the elbow method is a heuristic used in determining the number of clusters in a data set. The method consists of plotting the explained variation as a function of the number of clusters, and picking the elbow of the curve as the number of clusters to use.</p>
<pre><code>kmeans <span class="hljs-operator">=</span> KMeans()
visualizer <span class="hljs-operator">=</span> KElbowVisualizer(kmeans, k<span class="hljs-operator">=</span>(<span class="hljs-number">2</span>,<span class="hljs-number">15</span>))
visualizer.fit(df_sample)
visualizer.poof()
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643190834741/-H4kEUBF9.png" alt="__results___16_1.png" /></p>
<p>As you can see 5 clusters looks optimum for the data set and we already know this researh is to identify 5 different personalities.</p>
<h2 id="heading-clustering-participants-into-5-personality-groups">Clustering Participants into 5 Personality Groups</h2>
<p>To do this,  we use the unscaled data but without the country column.</p>
<pre><code>df_model = data.drop('country', axis=1)

<span class="hljs-comment"># I define 5 clusters and fit my model</span>
kmeans = KMeans(n_clusters=5)
k_fit = kmeans.fit(df_model)
<span class="hljs-comment">## SAVE KFIT MODEL</span>
joblib_file = <span class="hljs-string">"BigFivePersonalityTestModel.joblib"</span>
joblib.dump(k_fit, joblib_file)

<span class="hljs-comment"># Predicting the Clusters</span>
pd.options.display.max_columns = 10
predictions = k_fit.labels_
df_model['Clusters'] = predictions
df_model.head()
</code></pre><pre><code>
<span class="hljs-attribute">EXT1</span>    EXT<span class="hljs-number">2</span>    EXT<span class="hljs-number">3</span>    EXT<span class="hljs-number">4</span>    EXT<span class="hljs-number">5</span>    ...    OPN<span class="hljs-number">7</span>    OPN<span class="hljs-number">8</span>    OPN<span class="hljs-number">9</span>    OPN<span class="hljs-number">10</span>    Clusters
<span class="hljs-attribute">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">1</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    ...    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>
<span class="hljs-attribute">1</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    ...    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>
<span class="hljs-attribute">2</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    ...    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>
<span class="hljs-attribute">3</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">2</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    ...    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">4</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">1</span>
<span class="hljs-attribute">4</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    ...    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">5</span>.<span class="hljs-number">0</span>    <span class="hljs-number">3</span>
</code></pre><h2 id="heading-analysing-the-model-and-predictions">Analysing the Model and Predictions</h2>
<p>Let us see how many individuals we have for each cluster, like so:</p>
<pre><code><span class="hljs-selector-tag">df_model</span><span class="hljs-selector-class">.Clusters</span><span class="hljs-selector-class">.value_counts</span>()
</code></pre><pre><code><span class="hljs-number">4</span>    <span class="hljs-number">227063</span>
<span class="hljs-number">2</span>    <span class="hljs-number">212816</span>
<span class="hljs-number">3</span>    <span class="hljs-number">210075</span>
<span class="hljs-number">0</span>    <span class="hljs-number">200226</span>
<span class="hljs-number">1</span>    <span class="hljs-number">163301</span>
<span class="hljs-attr">Name:</span> <span class="hljs-string">Clusters,</span> <span class="hljs-attr">dtype:</span> <span class="hljs-string">int64</span>
</code></pre><p>Let's group the results acording to clusters. That way we can investigate the average answer to the each question for each cluster.</p>
<p>That way we can have an intuition about how our model classifies people.</p>
<pre><code>pd.options.display.max_columns <span class="hljs-operator">=</span> <span class="hljs-number">150</span>
df_model.groupby(<span class="hljs-string">'Clusters'</span>).mean()
</code></pre><p>Let's now sum up the each question groups (EXT, EST ..) and see if we can see a pattern.</p>
<pre><code><span class="hljs-comment"># Summing up the different questions groups</span>
<span class="hljs-attribute">col_list</span> = list(df_model)
<span class="hljs-attribute">ext</span> = col_list[<span class="hljs-number">0</span>:<span class="hljs-number">10</span>]
<span class="hljs-attribute">est</span> = col_list[<span class="hljs-number">10</span>:<span class="hljs-number">20</span>]
<span class="hljs-attribute">agr</span> = col_list[<span class="hljs-number">20</span>:<span class="hljs-number">30</span>]
<span class="hljs-attribute">csn</span> = col_list[<span class="hljs-number">30</span>:<span class="hljs-number">40</span>]
<span class="hljs-attribute">opn</span> = col_list[<span class="hljs-number">40</span>:<span class="hljs-number">50</span>]

<span class="hljs-attribute">data_sums</span> = pd.DataFrame()
<span class="hljs-attribute">data_sums</span>['extroversion'] = df_model[ext].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
<span class="hljs-attribute">data_sums</span>['neurotic'] = df_model[est].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
<span class="hljs-attribute">data_sums</span>['agreeable'] = df_model[agr].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
<span class="hljs-attribute">data_sums</span>['conscientious'] = df_model[csn].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
<span class="hljs-attribute">data_sums</span>['open'] = df_model[opn].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
<span class="hljs-attribute">data_sums</span>['clusters'] = predictions
<span class="hljs-attribute">data_sums</span>.groupby('clusters').mean()
</code></pre><pre><code>
<span class="hljs-attribute">extroversion</span>    neurotic    agreeable    conscientious    open
<span class="hljs-attribute">clusters</span>                    
<span class="hljs-attribute">0</span>    <span class="hljs-number">2</span>.<span class="hljs-number">965969</span>    <span class="hljs-number">3</span>.<span class="hljs-number">645931</span>    <span class="hljs-number">3</span>.<span class="hljs-number">148628</span>    <span class="hljs-number">3</span>.<span class="hljs-number">173210</span>    <span class="hljs-number">3</span>.<span class="hljs-number">245529</span>
<span class="hljs-attribute">1</span>    <span class="hljs-number">2</span>.<span class="hljs-number">909467</span>    <span class="hljs-number">2</span>.<span class="hljs-number">525743</span>    <span class="hljs-number">2</span>.<span class="hljs-number">851802</span>    <span class="hljs-number">2</span>.<span class="hljs-number">914458</span>    <span class="hljs-number">3</span>.<span class="hljs-number">120373</span>
<span class="hljs-attribute">2</span>    <span class="hljs-number">3</span>.<span class="hljs-number">051889</span>    <span class="hljs-number">2</span>.<span class="hljs-number">984940</span>    <span class="hljs-number">3</span>.<span class="hljs-number">187544</span>    <span class="hljs-number">3</span>.<span class="hljs-number">159140</span>    <span class="hljs-number">3</span>.<span class="hljs-number">243641</span>
<span class="hljs-attribute">3</span>    <span class="hljs-number">3</span>.<span class="hljs-number">085431</span>    <span class="hljs-number">2</span>.<span class="hljs-number">423577</span>    <span class="hljs-number">3</span>.<span class="hljs-number">209064</span>    <span class="hljs-number">3</span>.<span class="hljs-number">106899</span>    <span class="hljs-number">3</span>.<span class="hljs-number">327173</span>
<span class="hljs-attribute">4</span>    <span class="hljs-number">3</span>.<span class="hljs-number">072319</span>    <span class="hljs-number">3</span>.<span class="hljs-number">426610</span>    <span class="hljs-number">3</span>.<span class="hljs-number">300147</span>    <span class="hljs-number">3</span>.<span class="hljs-number">211454</span>    <span class="hljs-number">3</span>.<span class="hljs-number">352370</span>
</code></pre><p>Let us now visualize the mean for each of our 5 personality clusters:</p>
<pre><code><span class="hljs-comment"># Visualizing the means for each cluster</span>
<span class="hljs-attribute">dataclusters</span> = data_sums.groupby('clusters').mean()
<span class="hljs-attribute">plt</span>.figure(figsize=(<span class="hljs-number">22</span>,<span class="hljs-number">3</span>))
<span class="hljs-attribute">for</span> i in range(<span class="hljs-number">0</span>, <span class="hljs-number">5</span>):
    <span class="hljs-attribute">plt</span>.subplot(<span class="hljs-number">1</span>,<span class="hljs-number">5</span>,i+<span class="hljs-number">1</span>)
    <span class="hljs-attribute">plt</span>.bar(dataclusters.columns, dataclusters.iloc[:, i], color='green', alpha=<span class="hljs-number">0</span>.<span class="hljs-number">2</span>)
    <span class="hljs-attribute">plt</span>.plot(dataclusters.columns, dataclusters.iloc[:, i], color='red')
    <span class="hljs-attribute">plt</span>.title('Cluster ' + str(i))
    <span class="hljs-attribute">plt</span>.xticks(rotation=<span class="hljs-number">45</span>)
    <span class="hljs-attribute">plt</span>.ylim(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643191333284/18Bh_73nW.png" alt="__results___28_0.png" /></p>
<h2 id="heading-visualizing-the-cluster-predictions">Visualizing the Cluster Predictions</h2>
<pre><code>pca <span class="hljs-operator">=</span> PCA(n_components<span class="hljs-operator">=</span><span class="hljs-number">2</span>)
pca_fit <span class="hljs-operator">=</span> pca.fit_transform(df_model)

df_pca <span class="hljs-operator">=</span> pd.DataFrame(data<span class="hljs-operator">=</span>pca_fit, columns<span class="hljs-operator">=</span>[<span class="hljs-string">'PCA1'</span>, <span class="hljs-string">'PCA2'</span>])
df_pca[<span class="hljs-string">'Clusters'</span>] <span class="hljs-operator">=</span> predictions
df_pca.head()
plt.figure(figsize<span class="hljs-operator">=</span>(<span class="hljs-number">10</span>,<span class="hljs-number">10</span>))
sns.scatterplot(data<span class="hljs-operator">=</span>df_pca, x<span class="hljs-operator">=</span><span class="hljs-string">'PCA1'</span>, y<span class="hljs-operator">=</span><span class="hljs-string">'PCA2'</span>, hue<span class="hljs-operator">=</span><span class="hljs-string">'Clusters'</span>, palette<span class="hljs-operator">=</span><span class="hljs-string">'Set2'</span>, alpha<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.8</span>)
plt.title(<span class="hljs-string">'Personality Clusters after PCA'</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643191470229/PFydzsR_g.png" alt="__results___31_0.png" /></p>
<h2 id="heading-predict-personality">Predict Personality</h2>
<p>I answered the questions in an Microsoft Excel spread sheet. Then I added that data into this notebook and put my answers to the model to see in which category I will be.</p>
<pre><code>my_data <span class="hljs-operator">=</span> pd.read_excel(<span class="hljs-string">'my_personality_test.xlsx'</span>)
my_personality <span class="hljs-operator">=</span> k_fit.predict(my_data)
print(<span class="hljs-string">'My Personality Cluster: '</span>, my_personality)
</code></pre><pre><code><span class="hljs-attr">My Personality Cluster:</span>  [<span class="hljs-number">2</span>]
</code></pre><h2 id="heading-visualizing-my-personality-cluster">Visualizing my personality cluster</h2>
<pre><code>col_list <span class="hljs-operator">=</span> list(my_data)
ext <span class="hljs-operator">=</span> col_list[<span class="hljs-number">0</span>:<span class="hljs-number">10</span>]
est <span class="hljs-operator">=</span> col_list[<span class="hljs-number">10</span>:<span class="hljs-number">20</span>]
agr <span class="hljs-operator">=</span> col_list[<span class="hljs-number">20</span>:<span class="hljs-number">30</span>]
csn <span class="hljs-operator">=</span> col_list[<span class="hljs-number">30</span>:<span class="hljs-number">40</span>]
opn <span class="hljs-operator">=</span> col_list[<span class="hljs-number">40</span>:<span class="hljs-number">50</span>]

my_sums <span class="hljs-operator">=</span> pd.DataFrame()
my_sums[<span class="hljs-string">'extroversion'</span>] <span class="hljs-operator">=</span> my_data[ext].sum(axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)<span class="hljs-operator">/</span><span class="hljs-number">10</span>
my_sums[<span class="hljs-string">'neurotic'</span>] <span class="hljs-operator">=</span> my_data[est].sum(axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)<span class="hljs-operator">/</span><span class="hljs-number">10</span>
my_sums[<span class="hljs-string">'agreeable'</span>] <span class="hljs-operator">=</span> my_data[agr].sum(axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)<span class="hljs-operator">/</span><span class="hljs-number">10</span>
my_sums[<span class="hljs-string">'conscientious'</span>] <span class="hljs-operator">=</span> my_data[csn].sum(axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)<span class="hljs-operator">/</span><span class="hljs-number">10</span>
my_sums[<span class="hljs-string">'open'</span>] <span class="hljs-operator">=</span> my_data[opn].sum(axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)<span class="hljs-operator">/</span><span class="hljs-number">10</span>
my_sums[<span class="hljs-string">'cluster'</span>] <span class="hljs-operator">=</span> my_personality
print(<span class="hljs-string">'Sum of my question groups'</span>)
my_sums
my_sum <span class="hljs-operator">=</span> my_sums.drop(<span class="hljs-string">'cluster'</span>, axis<span class="hljs-operator">=</span><span class="hljs-number">1</span>)
plt.bar(my_sum.columns, my_sum.iloc[<span class="hljs-number">0</span>,:], color<span class="hljs-operator">=</span><span class="hljs-string">'green'</span>, alpha<span class="hljs-operator">=</span><span class="hljs-number">0</span><span class="hljs-number">.2</span>)
plt.plot(my_sum.columns, my_sum.iloc[<span class="hljs-number">0</span>,:], color<span class="hljs-operator">=</span><span class="hljs-string">'red'</span>)
plt.title(<span class="hljs-string">'Cluster 2'</span>)
plt.xticks(rotation<span class="hljs-operator">=</span><span class="hljs-number">45</span>)
plt.ylim(<span class="hljs-number">0</span>,<span class="hljs-number">4</span>);
</code></pre><p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1643191775139/Bvyj0lRN4.png" alt="__results___36_0.png" /></p>
<p>Now that our model works, let us proceed by turning our model into a Restful API</p>
<h2 id="heading-turning-the-model-into-an-restful-api">Turning the Model into an RESTFUL API</h2>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 <span class="hljs-operator">-</span>m venv myenv
$ source myenv<span class="hljs-operator">/</span>bin<span class="hljs-operator">/</span>activate
(myenv) $ pip install django requests numpy joblib scikit<span class="hljs-operator">-</span>learn xlsxwriter openpyxl
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests numpy joblib scikit-learn xlsxwriter openpyxl
</code></pre><h2 id="heading-setting-up-your-django-application">Setting Up Your Django Application</h2>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp<span class="hljs-operator">/</span>
    manage.py
    mainapp<span class="hljs-operator">/</span>
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp monitor
</code></pre><p>This will create the following:</p>
<pre><code>monitor<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code><span class="hljs-attr">INSTALLED_APPS</span> = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'monitor'</span>, <span class="hljs-comment">#new line</span>
]
</code></pre><p>Ensure you are in the monitor directory then create a new directory called templates then a new file called urls.py. Your directory structure of monitor application should look like this</p>
<pre><code>monitor<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
    templates<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our monitor app URL to include the URLs we shall create next on the monitor app:</p>
<pre><code><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> <span class="hljs-keyword">admin</span>
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>

urlpatterns = [
    #path(<span class="hljs-string">'admin/'</span>, <span class="hljs-keyword">admin</span>.site.urls),
    path(<span class="hljs-string">''</span>, <span class="hljs-keyword">include</span>(<span class="hljs-string">'monitor.urls'</span>)),#monitor app url
]
</code></pre><p>Now, on the monitor/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-title">path</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> .<span class="hljs-title">views</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-operator">*</span>

<span class="hljs-title">urlpatterns</span> <span class="hljs-operator">=</span> [
    <span class="hljs-title">path</span>(<span class="hljs-string">'persona'</span>, <span class="hljs-title">PersonalityPrediction</span>.<span class="hljs-title">as_view</span>(), <span class="hljs-title">name</span><span class="hljs-operator">=</span><span class="hljs-string">'personality'</span>),
]
</code></pre><p>Let’s create another directory to store our machine learning model. I’ll also add the dataset to the project for those who want to achieve the whole dataset. (It is not compulsory to create a data folder.) Be sure to move the vectorizer file and the joblib file we created earlier to ml/model folder</p>
<pre><code>(venv)$ <span class="hljs-keyword">mkdir</span> ml
(venv)$ <span class="hljs-keyword">mkdir</span> ml/models
(venv)$ <span class="hljs-keyword">mkdir</span> ml/data
</code></pre><p>We also need to tell Django where our machine learning model is located. Add these lines to settings.py file:</p>
<pre><code><span class="hljs-keyword">import</span> os
MODELS = os.path.<span class="hljs-keyword">join</span>(BASE_DIR, <span class="hljs-string">'ml/models'</span>)
</code></pre><h2 id="heading-load-model-and-vectorizer-through-appspy">Load Model and Vectorizer through apps.py</h2>
<p>Load the model we created and saved in apps.py so that when the application starts, the trained model is loaded only once. Otherwise, the trained model is loaded each time an endpoint is called, and then the response time will be slower. </p>
<p>Let’s update apps.py</p>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">from</span> django.apps <span class="hljs-keyword">import</span> AppConfig
<span class="hljs-keyword">from</span> django.conf <span class="hljs-keyword">import</span> settings


<span class="hljs-keyword">class</span> ApiConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'api'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "BigFivePersonalityTestModel.joblib")
    model = joblib.<span class="hljs-keyword">load</span>(MODEL_FILE)
</code></pre><h2 id="heading-edit-viewspy">Edit views.py</h2>
<p>The views will be mainly responsible for:</p>
<ul>
<li>Process incoming POST requests.</li>
</ul>
<pre><code><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render
<span class="hljs-keyword">from</span> rest_framework.views <span class="hljs-keyword">import</span> APIView
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> .apps <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> xlsxwriter

<span class="hljs-meta">#kmeans personality prediction view</span>
<span class="hljs-keyword">class</span> PersonalityPrediction(APIView):
    def post(self, request):
        #<span class="hljs-keyword">get</span> <span class="hljs-keyword">user</span> <span class="hljs-keyword">input</span>
        EXT1 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT1'</span>)
        EXT2 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT2'</span>)
        EXT3 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT3'</span>)
        EXT4 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT4'</span>)
        EXT5 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT5'</span>)
        EXT6 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT6'</span>)
        EXT7 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT7'</span>)
        EXT8 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT8'</span>)
        EXT9 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT9'</span>)
        EXT10 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EXT10'</span>)

        EST1 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST1'</span>)
        EST2 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST2'</span>)
        EST3 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST3'</span>)
        EST4 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST4'</span>)
        EST5 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST5'</span>)
        EST6 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST6'</span>)
        EST7 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST7'</span>)
        EST8 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST8'</span>)
        EST9 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST9'</span>)
        EST10 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'EST10'</span>)

        AGR1 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR1'</span>)
        AGR2 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR2'</span>)
        AGR3 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR3'</span>)
        AGR4 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR4'</span>)
        AGR5 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR5'</span>)
        AGR6 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR6'</span>)
        AGR7 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR7'</span>)
        AGR8 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR8'</span>)
        AGR9 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR9'</span>)
        AGR10 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'AGR10'</span>)

        CSN1 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN1'</span>)
        CSN2 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN2'</span>)
        CSN3 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN3'</span>)
        CSN4 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN4'</span>)
        CSN5 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN5'</span>)
        CSN6 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN6'</span>)
        CSN7 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN7'</span>)
        CSN8 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN8'</span>)
        CSN9 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN9'</span>)
        CSN10 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'CSN10'</span>)

        OPN1 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN1'</span>)
        OPN2 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN2'</span>)
        OPN3 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN3'</span>)
        OPN4 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN4'</span>)
        OPN5 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN5'</span>)
        OPN6 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN6'</span>)
        OPN7 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN7'</span>)
        OPN8 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN8'</span>)
        OPN9 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN9'</span>)
        OPN10 = request.data.<span class="hljs-keyword">get</span>(<span class="hljs-string">'OPN10'</span>)
        #<span class="hljs-keyword">load</span> model
        kmeansModel = PersonalityTestConfig.model
        # Predicting the Clusters
        pd.<span class="hljs-keyword">options</span>.display.max_columns = <span class="hljs-number">10</span>
        predictions = kmeansModel.labels_

        workbook = xlsxwriter.Workbook(<span class="hljs-string">'hello.xlsx'</span>)

        worksheet = workbook.add_worksheet()

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'A1'</span>, <span class="hljs-string">'EXT1'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'A2'</span>, (EXT1))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'B1'</span>, <span class="hljs-string">'EXT2'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'B2'</span>, (EXT2))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'C1'</span>, <span class="hljs-string">'EXT3'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'C2'</span>, (EXT3))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'D1'</span>, <span class="hljs-string">'EXT4'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'D2'</span>, (EXT4))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'E1'</span>, <span class="hljs-string">'EXT5'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'E2'</span>, (EXT5))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'F1'</span>, <span class="hljs-string">'EXT6'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'F2'</span>, (EXT6))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'G1'</span>, <span class="hljs-string">'EXT7'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'G2'</span>, (EXT7))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'H1'</span>, <span class="hljs-string">'EXT8'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'H2'</span>, (EXT8))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'I1'</span>, <span class="hljs-string">'EXT9'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'I2'</span>, (EXT9))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'J1'</span>, <span class="hljs-string">'EXT10'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'J2'</span>, (EXT10))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'K1'</span>, <span class="hljs-string">'EST1'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'K2'</span>, (EST1))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'L1'</span>, <span class="hljs-string">'EST2'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'L2'</span>, (EST2))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'M1'</span>, <span class="hljs-string">'EST3'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'M2'</span>, (EST3))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'N1'</span>, <span class="hljs-string">'EST4'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'N2'</span>, (EST4))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'O1'</span>, <span class="hljs-string">'EST5'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'O2'</span>, (EST5))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'P1'</span>, <span class="hljs-string">'EST6'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'P2'</span>, (EST6))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Q1'</span>, <span class="hljs-string">'EST7'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Q2'</span>, (EST7))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'R1'</span>, <span class="hljs-string">'EST8'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'R2'</span>, (EST8))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'S1'</span>, <span class="hljs-string">'EST9'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'S2'</span>, (EST9))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'T1'</span>, <span class="hljs-string">'EST10'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'T2'</span>, (EST10))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'U1'</span>, <span class="hljs-string">'AGR1'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'U2'</span>, (AGR1))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'V1'</span>, <span class="hljs-string">'AGR2'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'V2'</span>, (AGR2))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'W1'</span>, <span class="hljs-string">'AGR3'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'W2'</span>, (AGR3))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'X1'</span>, <span class="hljs-string">'AGR4'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'X2'</span>, (AGR4))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Y1'</span>, <span class="hljs-string">'AGR5'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Y2'</span>, (AGR5))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Z1'</span>, <span class="hljs-string">'AGR6'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'Z2'</span>, (AGR6))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AA1'</span>, <span class="hljs-string">'AGR7'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AA2'</span>, (AGR7))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AB1'</span>, <span class="hljs-string">'AGR8'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AB2'</span>, (AGR8))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AC1'</span>, <span class="hljs-string">'AGR9'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AC2'</span>, (AGR9))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AD1'</span>, <span class="hljs-string">'AGR10'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AD2'</span>, (AGR10))


        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AE1'</span>, <span class="hljs-string">'CSN1'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AE2'</span>, (CSN1))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AF1'</span>, <span class="hljs-string">'CSN2'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AF2'</span>, (CSN2))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AG1'</span>, <span class="hljs-string">'CSN3'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AG2'</span>, (CSN3))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AH1'</span>, <span class="hljs-string">'CSN4'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AH2'</span>, (CSN4))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AI1'</span>, <span class="hljs-string">'CSN5'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AI2'</span>, (CSN5))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AJ1'</span>, <span class="hljs-string">'CSN6'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AJ2'</span>, (CSN6))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AK1'</span>, <span class="hljs-string">'CSN7'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AK2'</span>, (CSN7))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AL1'</span>, <span class="hljs-string">'CSN8'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AL2'</span>, (CSN8))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AM1'</span>, <span class="hljs-string">'CSN9'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AM2'</span>, (CSN9))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AN1'</span>, <span class="hljs-string">'CSN10'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AN2'</span>, (CSN10))


        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AO1'</span>, <span class="hljs-string">'OPN1'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AO2'</span>, (OPN1))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AP1'</span>, <span class="hljs-string">'OPN2'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AP2'</span>, (OPN2))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AQ1'</span>, <span class="hljs-string">'OPN3'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AQ2'</span>, (OPN3))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AR1'</span>, <span class="hljs-string">'OPN4'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AR2'</span>, (OPN4))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AS1'</span>, <span class="hljs-string">'OPN5'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AS2'</span>, (OPN5))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AT1'</span>, <span class="hljs-string">'OPN6'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AT2'</span>, (OPN6))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AU1'</span>, <span class="hljs-string">'OPN7'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AU2'</span>, (OPN7))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AV1'</span>, <span class="hljs-string">'OPN8'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AV2'</span>, (OPN8))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AW1'</span>, <span class="hljs-string">'OPN9'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AW2'</span>, (OPN9))

        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AX1'</span>, <span class="hljs-string">'OPN10'</span>)
        worksheet.<span class="hljs-keyword">write</span>(<span class="hljs-string">'AX2'</span>, (OPN10))


        # Finally, <span class="hljs-keyword">close</span> the Excel file
        # via the <span class="hljs-keyword">close</span>() <span class="hljs-keyword">method</span>.
        workbook.<span class="hljs-keyword">close</span>()

        my_data = pd.read_excel(<span class="hljs-string">'hello.xlsx'</span>, engine=<span class="hljs-string">'openpyxl'</span>)

        my_personality = kmeansModel.predict(my_data)
        print(<span class="hljs-string">'My Personality Cluster: '</span>, my_personality)

        # Summing up the my question <span class="hljs-keyword">groups</span>
        col_list = list(my_data)
        ext = col_list[<span class="hljs-number">0</span>:<span class="hljs-number">10</span>]
        est = col_list[<span class="hljs-number">10</span>:<span class="hljs-number">20</span>]
        agr = col_list[<span class="hljs-number">20</span>:<span class="hljs-number">30</span>]
        csn = col_list[<span class="hljs-number">30</span>:<span class="hljs-number">40</span>]
        opn = col_list[<span class="hljs-number">40</span>:<span class="hljs-number">50</span>]

        my_sums = pd.DataFrame()
        my_sums[<span class="hljs-string">'extroversion'</span>] = my_data[ext].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
        my_sums[<span class="hljs-string">'neurotic'</span>] = my_data[est].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
        my_sums[<span class="hljs-string">'agreeable'</span>] = my_data[agr].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
        my_sums[<span class="hljs-string">'conscientious'</span>] = my_data[csn].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
        my_sums[<span class="hljs-string">'open'</span>] = my_data[opn].sum(axis=<span class="hljs-number">1</span>)/<span class="hljs-number">10</span>
        my_sums[<span class="hljs-string">'cluster'</span>] = my_personality
        print(<span class="hljs-string">'Sum of my question groups'</span>)
        print(my_sums)

        response_dict = {"Prediction": my_sums}
        print(response_dict)
        <span class="hljs-keyword">return</span> Response(response_dict, status=<span class="hljs-number">200</span>)
</code></pre><p>The code above starts by getting the data appended to the request body. The code then creates a new excel file programmatically which is used in the prediction and returns the cluster as a response.</p>
<h2 id="heading-testing-our-model">Testing our model.</h2>
<p>To test the system, make the necessary migrations and run the django server. Open POSTMAN and make a POST request to our server like so, with the answers to the questionnaire appended to the body of the request. We should get a sample response showing us our personality cluster and our scores.
To test my live system, make a POST request to the URL below:</p>
<pre><code><span class="hljs-attribute">https</span>:<span class="hljs-comment">//alienx.tech/api/v1/persona</span>
</code></pre><p>The code below is what i used to prompt GPT3 to help me generate the content in this blog:</p>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">openai</span>
<span class="hljs-title">openai</span>.<span class="hljs-title">api_key</span> <span class="hljs-operator">=</span> <span class="hljs-string">"VISIT OPENAI TO GET YOUR KEY"</span>
<span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">openai</span>.<span class="hljs-title">Completion</span>.<span class="hljs-title">create</span>(
  <span class="hljs-title">engine</span><span class="hljs-operator">=</span><span class="hljs-string">"davinci"</span>,
  <span class="hljs-title">prompt</span><span class="hljs-operator">=</span><span class="hljs-string">"The Pixel District Janury 16, 2022n Title: Personality Segmentation Using K-Means Clustering Algorithm and Django Rest Framework!n tags: machine-learning, kmeans, gpt3, kmeans code sample Summary:  I am sharing my exprience in implementing kmeans clustering algorithmn in determining someones personality. I am explaining why kmeans clustering algorithms is, how it works configuration. I am explaining what the big five personality traits are. I am explaining why I think kmeans algorithm is the best to use in finding someones personality based on the  big five personality traits. I am also adding various example codes of the kmeans clustering to find the big five personality traits.n Full text: "</span>,
  <span class="hljs-title">temperature</span><span class="hljs-operator">=</span>0.7,
  <span class="hljs-title">max_tokens</span><span class="hljs-operator">=</span>1655,
  <span class="hljs-title">top_p</span><span class="hljs-operator">=</span>1,
  <span class="hljs-title">frequency_penalty</span><span class="hljs-operator">=</span>0,
  <span class="hljs-title">presence_penalty</span><span class="hljs-operator">=</span>0
)
<span class="hljs-title">print</span>(<span class="hljs-title">response</span>)
</code></pre><p>That's it for today. Thanks for staying tuned in!</p>
]]></content:encoded></item><item><title><![CDATA[How to Restore Dislikes on YouTube with Django Rest Framework and YoutubeV3 API.]]></title><description><![CDATA[UPDATE
Youtube has taken down the view count API and this functionality is no longer functional
Overview:
Earlier this month, video sharing service YouTube, which is now the second-most-used platform online, announced that while the "dislike" button ...]]></description><link>https://blog.paulwababu.me.ke/how-to-restore-dislikes-on-youtube-with-django-rest-framework-and-youtubev3-api</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/how-to-restore-dislikes-on-youtube-with-django-rest-framework-and-youtubev3-api</guid><category><![CDATA[APIs]]></category><category><![CDATA[youtube]]></category><category><![CDATA[Developer]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Wed, 01 Dec 2021 15:23:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638254698993/qLumChota.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-update"><strong>UPDATE</strong></h2>
<p>Youtube has taken down the view count API and this functionality is no longer functional</p>
<h2 id="heading-overview">Overview:</h2>
<p>Earlier this month, video sharing service YouTube, which is now the second-most-used platform online, announced that while the "dislike" button would remain, the actual dislike count would be made private.</p>
<p>"To ensure that YouTube promotes respectful interactions between viewers and creators, we introduced several features and policies to improve their experience," the company announced via a blog post. "And earlier this year, we experimented with the dislike button to see whether or not changes could help better protect our creators from harassment, and reduce dislike attacks — where people work to drive up the number of dislikes on a creator’s videos."</p>
<p>While the removal of public dislikes could help the creators, there is the argument this is also about helping YouTube by getting more eyeballs on videos – even ones that could disappoint some viewers. The lack of "dislikes" means there is no quick public review of the user-generated content.</p>
<h2 id="heading-introduction">Introduction</h2>
<p>In this article, we will see how we can display the dislike count of any youtube video using <a target="_blank" href="https://developers.google.com/youtube/v3">YoutubeV3 API</a> and Django Rest Framework.</p>
<p>To test my live system, head over to a youtube video of your choice on the web: </p>
<ul>
<li>Replace "<a target="_blank" href="www.youtube.com">www.youtube.com</a>":</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638355114034/VuOSSjtZW.png" alt="yes1.png" /></p>
<ul>
<li>With "<a target="_blank" href="https://alienx.tech/">alienx.tech</a>":</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638361519307/CfPi5bhlY.png" alt="as.png" /></p>
<p>Be sure not to change the video-ID and ensure you remove the "www" otherwise you will get a privacy error, then hit enter.</p>
<p>If successful, your browser will redirect to the page below which displays both the like and dislike count:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638310748702/F8z_d7YAj.png" alt="3.png" /></p>
<p>Before we dive into building our microservice, let us start by understanding how I was able to achieve this.</p>
<h2 id="heading-how-it-works">How it Works</h2>
<p>It is worth stating that I got this idea from <a target="_blank" href="https://www.y2mate.com/">y2mate</a> which is a free youtube downloader website that works by inserting "pp" after the word "youtube" in the link, like so:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638357694789/4iaKAKvsB.jpeg" alt="tip-download-youtube.jpg" /></p>
<p>The first thing I needed to do was to create an API route to be like youtube is on my Django backend. I also needed the youtube API for collecting the data about the video at play. Surprisingly, youtube has not made that functionality private which is fair enough.</p>
<p>I did not find Youtubes' <a target="_blank" href="https://developers.google.com/youtube/v3/docs">API docs</a> to be user friendly and so I did some digging where I came across this god-sent freemium app on <a target="_blank" href="https://rapidapi.com/ytdlfree/api/youtube-v31/">RapidAPI</a> that enables you to use the youtube V3 API without having an API key from Google developers account! The app is very well maintained and has a low ping. PS: I was able to tell it's an awesome API by just looking at the ranking score it got on rapid API so negative feedback can actually help save you money;). Imagine subscribing to a paid API that turns out to be very slow yet you could have looked at the like to dislike ratio.</p>
<p>On my Django Rest backend side, I needed <a target="_blank" href="https://blog.alienx.tech/introduction-what-is-prometheus">prometheus</a>,(the name of my API server), to make a request to youtubeV3 API, then return the response to the user as a template, not json or any other format. Django being the most powerful web development framework, in my opinion, has an inbuilt function for doing this called <a target="_blank" href="https://www.django-rest-framework.org/api-guide/renderers/">Renderers</a>. The rendering process works by taking the intermediate representation of the template and context and turning it into the final byte stream that can be served to the client.</p>
<h2 id="heading-building-our-api">Building our API</h2>
<p>For this tutorial, we shall be using python3.5+, Django Rest Web Framework, and Youtube's v3 API for pulling youtube video data including the dislike count.</p>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip3 install django djangorestframework requests
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip3 install django djangorestframework requests
</code></pre><h3 id="heading-youtube-v3-api">Youtube V3 API</h3>
<p>As mentioned earlier, I will not be accessing youtube's API using my own access token, I will be using a third-party app found on rapid API which is one of the largest API marketplaces on the web. Create an account with rapid API to get the freemium <a target="_blank" href="https://rapidapi.com/ytdlfree/api/youtube-v31">youtubeV3API</a></p>
<h3 id="heading-setting-up-your-django-application">Setting Up Your Django Application</h3>
<p>First, navigate to the directory Django app we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp<span class="hljs-operator">/</span>
    manage.py
    mainapp<span class="hljs-operator">/</span>
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp exam
</code></pre><p>This will create the following:</p>
<pre><code>exam<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code>INSTALLED_APPS = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'django.contrib.humanize'</span>,#<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>, explanation later
    <span class="hljs-string">'rest_framework'</span>,#<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
    <span class="hljs-string">'exam'</span>, #<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
]
</code></pre><p>Ensure you are in the exam directory then create a new directory called templates and a new file called urls.py. Your directory structure of exam application should look like this</p>
<pre><code>exam<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
    templates<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our exam app URL to include the URLs we shall create next on the exam app:</p>
<pre><code><span class="hljs-string">"""mainapp URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""</span>
<span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path, include

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">' '</span>, include(<span class="hljs-string">'exam.urls'</span>)),<span class="hljs-comment">#exam app url</span>
]
</code></pre><p>Now, on the exam/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>
<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> views

urlpatterns = [
    path(<span class="hljs-string">'watch'</span>, YoutubeStats.as_view(), <span class="hljs-type">name</span>="youtubestats"),
]
</code></pre><p>On the exam/views.py, add the following lines of code: </p>
<pre><code><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> <span class="hljs-title">render</span>, <span class="hljs-title">redirect</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">requests</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">django</span>.<span class="hljs-title">http</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">HttpResponse</span>, <span class="hljs-title">HttpResponseRedirect</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">rest_framework</span>.<span class="hljs-title">response</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">Response</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">rest_framework</span>.<span class="hljs-title">views</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">APIView</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">rest_framework</span>.<span class="hljs-title">renderers</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">TemplateHTMLRenderer</span>

<span class="hljs-title">class</span> <span class="hljs-title">YoutubeStats</span>(<span class="hljs-title">APIView</span>):
      <span class="hljs-title">renderer_classes</span> <span class="hljs-operator">=</span> [<span class="hljs-title">TemplateHTMLRenderer</span>]
      <span class="hljs-title">template_name</span> <span class="hljs-operator">=</span> <span class="hljs-string">'youtube.html'</span>

      <span class="hljs-title">def</span> <span class="hljs-title">get</span>(<span class="hljs-title"><span class="hljs-built_in">self</span></span>, <span class="hljs-title">request</span>):
          <span class="hljs-title">toScan</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'v'</span>) #<span class="hljs-title">get</span> <span class="hljs-title">users</span> <span class="hljs-title">request</span>(<span class="hljs-title">video</span> <span class="hljs-title">URL</span> <span class="hljs-title">in</span> <span class="hljs-title"><span class="hljs-built_in">this</span></span> <span class="hljs-title">case</span>)
          #<span class="hljs-title">youtubev3</span> <span class="hljs-title">api</span>
          <span class="hljs-title">parsed</span> <span class="hljs-operator">=</span> <span class="hljs-title">str</span>(<span class="hljs-title">toScan</span>) #<span class="hljs-title">convert</span> <span class="hljs-title">to</span> <span class="hljs-title"><span class="hljs-keyword">string</span></span>
          <span class="hljs-title">url</span> <span class="hljs-operator">=</span> <span class="hljs-string">'https://youtube-v31.p.rapidapi.com/videos'</span>
          <span class="hljs-title">querystring</span> <span class="hljs-operator">=</span> {<span class="hljs-string">"part"</span>:<span class="hljs-string">"contentDetails,snippet,statistics"</span>,<span class="hljs-string">"id"</span>:<span class="hljs-title">parsed</span>} 
          <span class="hljs-title">headers</span> <span class="hljs-operator">=</span> {<span class="hljs-string">'x-rapidapi-host'</span>: <span class="hljs-string">"youtube-v31.p.rapidapi.com"</span>,<span class="hljs-string">'x-rapidapi-key'</span>: <span class="hljs-string">"GETYOURKEY"</span>}
          <span class="hljs-title">response</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">request</span>(<span class="hljs-string">"GET"</span>, <span class="hljs-title">url</span>, <span class="hljs-title">headers</span><span class="hljs-operator">=</span><span class="hljs-title">headers</span>, <span class="hljs-title">params</span><span class="hljs-operator">=</span><span class="hljs-title">querystring</span>)
          <span class="hljs-title">DataResponse</span> <span class="hljs-operator">=</span> <span class="hljs-title">response</span>.<span class="hljs-title">json</span>() 
          <span class="hljs-title">items</span> <span class="hljs-operator">=</span> <span class="hljs-title">DataResponse</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'items'</span>)
          <span class="hljs-title"><span class="hljs-keyword">for</span></span> <span class="hljs-title">data</span> <span class="hljs-title">in</span> <span class="hljs-title">items</span>:
              <span class="hljs-title">chanid</span> <span class="hljs-operator">=</span> <span class="hljs-title">data</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'snippet'</span>)
              <span class="hljs-title">channelid</span> <span class="hljs-operator">=</span> <span class="hljs-title">chanid</span>[<span class="hljs-string">'channelId'</span>]
          #<span class="hljs-title">context</span> <span class="hljs-operator">=</span> {<span class="hljs-string">'items'</span>:<span class="hljs-title">items</span>, <span class="hljs-string">'videoid'</span>:<span class="hljs-title">parsed</span>}
          <span class="hljs-title">url2</span> <span class="hljs-operator">=</span> <span class="hljs-string">"https://youtube-v31.p.rapidapi.com/channels"</span>
          <span class="hljs-title">querystring2</span> <span class="hljs-operator">=</span> {<span class="hljs-string">"part"</span>:<span class="hljs-string">"snippet,statistics"</span>,<span class="hljs-string">"id"</span>:<span class="hljs-title">channelid</span>}
          <span class="hljs-title">response2</span> <span class="hljs-operator">=</span> <span class="hljs-title">requests</span>.<span class="hljs-title">request</span>(<span class="hljs-string">"GET"</span>, <span class="hljs-title">url2</span>, <span class="hljs-title">headers</span><span class="hljs-operator">=</span><span class="hljs-title">headers</span>, <span class="hljs-title">params</span><span class="hljs-operator">=</span><span class="hljs-title">querystring2</span>)
          <span class="hljs-title">DataResponse2</span> <span class="hljs-operator">=</span> <span class="hljs-title">response2</span>.<span class="hljs-title">json</span>()
          <span class="hljs-title">items2</span> <span class="hljs-operator">=</span> <span class="hljs-title">DataResponse2</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'items'</span>)
          <span class="hljs-title">context</span> <span class="hljs-operator">=</span> {<span class="hljs-string">'items'</span>:<span class="hljs-title">items</span>, <span class="hljs-string">'videoid'</span>:<span class="hljs-title">parsed</span>, <span class="hljs-string">'items2'</span>:<span class="hljs-title">items2</span>,}
          <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">Response</span>(<span class="hljs-title">context</span>)
</code></pre><h3 id="heading-explanation-of-viewspy">Explanation of views.py</h3>
<p>In the code above, we start by getting initiating the template class and template name of our API. We then get the request of the user that was appended to the video to be analyzed ('v'). We then proceed by converting the requested videoID to a string and then making a request to the youtube API. </p>
<p>The sample response from youtube API looks like so:</p>
<pre><code>{
   <span class="hljs-attr">"kind"</span>:<span class="hljs-string">"youtube#videoListResponse"</span>,
   <span class="hljs-attr">"items"</span>:[
      {
         <span class="hljs-attr">"kind"</span>:<span class="hljs-string">"youtube#video"</span>,
         <span class="hljs-attr">"id"</span>:<span class="hljs-string">"frn3WT15Dy8"</span>,
         <span class="hljs-attr">"snippet"</span>:{
            <span class="hljs-attr">"publishedAt"</span>:<span class="hljs-string">"2021-11-23T01:30:12Z"</span>,
            <span class="hljs-attr">"channelId"</span>:<span class="hljs-string">"UCPWXiRWZ29zrxPFIQT7eHSA"</span>,
            <span class="hljs-attr">"title"</span>:<span class="hljs-string">"'This Is Now Becoming A Pattern': Jordan Slams YouTube Covid-19 'Censorship'"</span>,
            <span class="hljs-attr">"description"</span>:<span class="hljs-string">"During a Wednesday hearing on COVID-19 misinformation, Rep. Jim Jordan (R-OH) criticized YouTube for removing a video containing 'misinformation.' The Ohio Republican said the social media company should not be censoring doctors over 'science.'"</span>,
            <span class="hljs-attr">"thumbnails"</span>:{
               <span class="hljs-attr">"default"</span>:{
                  <span class="hljs-attr">"url"</span>:<span class="hljs-string">"https://i.ytimg.com/vi/frn3WT15Dy8/default.jpg"</span>,
                  <span class="hljs-attr">"width"</span>:<span class="hljs-number">120</span>,
                  <span class="hljs-attr">"height"</span>:<span class="hljs-number">90</span>
               },
               <span class="hljs-attr">"medium"</span>:{
                  <span class="hljs-attr">"url"</span>:<span class="hljs-string">"https://i.ytimg.com/vi/frn3WT15Dy8/mqdefault.jpg"</span>,
                  <span class="hljs-attr">"width"</span>:<span class="hljs-number">320</span>,
                  <span class="hljs-attr">"height"</span>:<span class="hljs-number">180</span>
               },
               <span class="hljs-attr">"high"</span>:{
                  <span class="hljs-attr">"url"</span>:<span class="hljs-string">"https://i.ytimg.com/vi/frn3WT15Dy8/hqdefault.jpg"</span>,
                  <span class="hljs-attr">"width"</span>:<span class="hljs-number">480</span>,
                  <span class="hljs-attr">"height"</span>:<span class="hljs-number">360</span>
               },
               <span class="hljs-attr">"standard"</span>:{
                  <span class="hljs-attr">"url"</span>:<span class="hljs-string">"https://i.ytimg.com/vi/frn3WT15Dy8/sddefault.jpg"</span>,
                  <span class="hljs-attr">"width"</span>:<span class="hljs-number">640</span>,
                  <span class="hljs-attr">"height"</span>:<span class="hljs-number">480</span>
               },
               <span class="hljs-attr">"maxres"</span>:{
                  <span class="hljs-attr">"url"</span>:<span class="hljs-string">"https://i.ytimg.com/vi/frn3WT15Dy8/maxresdefault.jpg"</span>,
                  <span class="hljs-attr">"width"</span>:<span class="hljs-number">1280</span>,
                  <span class="hljs-attr">"height"</span>:<span class="hljs-number">720</span>
               }
            },
            <span class="hljs-attr">"channelTitle"</span>:<span class="hljs-string">"The Hill"</span>,
            <span class="hljs-attr">"categoryId"</span>:<span class="hljs-string">"25"</span>,
            <span class="hljs-attr">"liveBroadcastContent"</span>:<span class="hljs-string">"none"</span>,
            <span class="hljs-attr">"defaultLanguage"</span>:<span class="hljs-string">"en-US"</span>,
            <span class="hljs-attr">"localized"</span>:{
               <span class="hljs-attr">"title"</span>:<span class="hljs-string">"'This Is Now Becoming A Pattern': Jordan Slams YouTube Covid-19 'Censorship'"</span>,
               <span class="hljs-attr">"description"</span>:<span class="hljs-string">"During a Wednesday hearing on COVID-19 misinformation, Rep. Jim Jordan (R-OH) criticized YouTube for removing a video containing 'misinformation.' The Ohio Republican said the social media company should not be censoring doctors over 'science.'"</span>
            },
            <span class="hljs-attr">"defaultAudioLanguage"</span>:<span class="hljs-string">"en-US"</span>
         },
         <span class="hljs-attr">"contentDetails"</span>:{
            <span class="hljs-attr">"duration"</span>:<span class="hljs-string">"PT6M19S"</span>,
            <span class="hljs-attr">"dimension"</span>:<span class="hljs-string">"2d"</span>,
            <span class="hljs-attr">"definition"</span>:<span class="hljs-string">"hd"</span>,
            <span class="hljs-attr">"caption"</span>:<span class="hljs-string">"false"</span>,
            <span class="hljs-attr">"licensedContent"</span>:<span class="hljs-literal">true</span>,
            <span class="hljs-attr">"contentRating"</span>:{

            },
            <span class="hljs-attr">"projection"</span>:<span class="hljs-string">"rectangular"</span>
         },
         <span class="hljs-attr">"statistics"</span>:{
            <span class="hljs-attr">"viewCount"</span>:<span class="hljs-string">"989839"</span>,
            <span class="hljs-attr">"likeCount"</span>:<span class="hljs-string">"35804"</span>,
            <span class="hljs-attr">"dislikeCount"</span>:<span class="hljs-string">"798"</span>,
            <span class="hljs-attr">"favoriteCount"</span>:<span class="hljs-string">"0"</span>,
            <span class="hljs-attr">"commentCount"</span>:<span class="hljs-string">"7034"</span>
         }
      }
   ],
   <span class="hljs-attr">"pageInfo"</span>:{
      <span class="hljs-attr">"totalResults"</span>:<span class="hljs-number">1</span>,
      <span class="hljs-attr">"resultsPerPage"</span>:<span class="hljs-number">1</span>
   }
}
</code></pre><p>In order to get the title and subscriber count of the channel owner, we need to make another request to the channels API. We append the channel_ID to the querystring2 and then make a request to the channels API. We then proceed to render the context as the final response on our HTML template that we shall create below.</p>
<h3 id="heading-youtube-template">Youtube Template</h3>
<p>On the exam/templates/ folder, create a youtube.html file and add the following lines of code: </p>
<pre><code>{% load humanize %}
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>
      <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
      <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-keyword">@import</span> url(<span class="hljs-attribute">https:</span>//fonts.googleapis.com/css2?family=Roboto&amp;display=swap);*{<span class="hljs-attribute">margin</span>:<span class="hljs-number">0</span>;<span class="hljs-attribute">padding</span>:<span class="hljs-number">0</span>;<span class="hljs-attribute">box-sizing</span>:border-box}<span class="hljs-selector-tag">body</span>{<span class="hljs-attribute">background-color</span>:<span class="hljs-built_in">rgba</span>(<span class="hljs-number">200</span>,<span class="hljs-number">200</span>,<span class="hljs-number">200</span>,.<span class="hljs-number">1</span>);<span class="hljs-attribute">font-family</span>:Roboto,sans-serif}<span class="hljs-selector-class">.icon-spacing</span>{<span class="hljs-attribute">padding</span>:<span class="hljs-number">0</span> <span class="hljs-number">10px</span>}<span class="hljs-selector-class">.flex-column</span>{<span class="hljs-attribute">flex-direction</span>:column}<span class="hljs-selector-class">.space-between</span>{<span class="hljs-attribute">justify-content</span>:space-between}<span class="hljs-selector-class">.grid-container</span>{<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">left</span>:<span class="hljs-number">250px</span>}<span class="hljs-selector-tag">nav</span>{<span class="hljs-attribute">align-items</span>:center;<span class="hljs-attribute">position</span>:fixed;<span class="hljs-attribute">top</span>:<span class="hljs-number">0</span>;<span class="hljs-attribute">width</span>:<span class="hljs-number">100%</span>;<span class="hljs-attribute">height</span>:<span class="hljs-number">50px</span>;<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#fff</span>;<span class="hljs-attribute">justify-content</span>:space-between;<span class="hljs-attribute">z-index</span>:<span class="hljs-number">1</span>}<span class="hljs-selector-id">#left-navbar</span>{<span class="hljs-attribute">justify-content</span>:space-evenly;<span class="hljs-attribute">width</span>:<span class="hljs-number">12%</span>;<span class="hljs-attribute">align-items</span>:center;<span class="hljs-attribute">margin-left</span>:<span class="hljs-number">15px</span>}<span class="hljs-selector-id">#mid-navbar</span>{<span class="hljs-attribute">align-self</span>:center;<span class="hljs-attribute">margin-right</span>:<span class="hljs-number">20px</span>;<span class="hljs-attribute">width</span>:<span class="hljs-number">50%</span>;<span class="hljs-attribute">justify-content</span>:center}<span class="hljs-selector-id">#search-bar</span>{<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#fff</span>;<span class="hljs-attribute">width</span>:<span class="hljs-number">85%</span>;<span class="hljs-attribute">padding</span>:<span class="hljs-number">3px</span> <span class="hljs-number">10px</span>;<span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid silver;<span class="hljs-attribute">border-radius</span>:<span class="hljs-number">3px</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">3px</span>;<span class="hljs-attribute">font-size</span>:medium}<span class="hljs-selector-id">#search-button</span>{<span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid gray;<span class="hljs-attribute">padding</span>:<span class="hljs-number">0</span> <span class="hljs-number">30px</span>;<span class="hljs-attribute">border-radius</span>:<span class="hljs-number">0</span> <span class="hljs-number">3px</span> <span class="hljs-number">3px</span> <span class="hljs-number">0</span>}<span class="hljs-selector-id">#right-navbar</span>{<span class="hljs-attribute">align-items</span>:center;<span class="hljs-attribute">width</span>:<span class="hljs-number">120px</span>;<span class="hljs-attribute">justify-content</span>:space-between;<span class="hljs-attribute">margin-right</span>:<span class="hljs-number">50px</span>}<span class="hljs-selector-class">.main-video</span>{<span class="hljs-attribute">margin-left</span>:initial}<span class="hljs-selector-class">.flex</span>{<span class="hljs-attribute">display</span>:flex}<span class="hljs-selector-class">.upcoming</span>{<span class="hljs-attribute">font-family</span>:Roboto,sans-serif;<span class="hljs-attribute">font-size</span>:<span class="hljs-number">16px</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#030303</span>}<span class="hljs-selector-class">.input</span>{<span class="hljs-attribute">width</span>:<span class="hljs-number">550px</span>;<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">left</span>:<span class="hljs-number">219px</span>}<span class="hljs-selector-class">.container</span>{<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">top</span>:<span class="hljs-number">85px</span>;<span class="hljs-attribute">left</span>:<span class="hljs-number">22px</span>}<span class="hljs-selector-class">.main-fc</span>{<span class="hljs-attribute">width</span>:<span class="hljs-number">60%</span>;<span class="hljs-attribute">margin-left</span>:<span class="hljs-number">30px</span>}<span class="hljs-selector-class">.other-videos</span>{<span class="hljs-attribute">width</span>:<span class="hljs-number">30%</span>}<span class="hljs-selector-id">#autobutton</span>{<span class="hljs-attribute">border</span>:none;<span class="hljs-attribute">background-color</span>:transparent}<span class="hljs-selector-class">.sidebar</span>{<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">top</span>:<span class="hljs-number">80px</span>}<span class="hljs-selector-class">.image</span>{<span class="hljs-attribute">float</span>:left;<span class="hljs-attribute">height</span>:<span class="hljs-number">10px</span>;<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">width</span>:<span class="hljs-number">168px</span>}<span class="hljs-selector-class">.aside-video</span>{<span class="hljs-attribute">grid-template-columns</span>:<span class="hljs-number">180px</span> <span class="hljs-number">180px</span>;<span class="hljs-attribute">display</span>:grid;<span class="hljs-attribute">margin-bottom</span>:<span class="hljs-number">4px</span>}<span class="hljs-selector-class">.song-title</span>{<span class="hljs-attribute">font-size</span>:<span class="hljs-number">14px</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#030303</span>;<span class="hljs-attribute">display</span>:inline-block}<span class="hljs-selector-class">.aside-description</span>{<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">bottom</span>:<span class="hljs-number">8px</span>;<span class="hljs-attribute">font-size</span>:<span class="hljs-number">12px</span>}<span class="hljs-selector-class">.artist-name</span>{<span class="hljs-attribute">font-size</span>:<span class="hljs-number">13px</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#606060</span>}<span class="hljs-selector-class">.aside-views</span>{<span class="hljs-attribute">font-size</span>:<span class="hljs-number">13px</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#606060</span>}<span class="hljs-selector-class">.video-duration</span>{<span class="hljs-attribute">position</span>:relative;<span class="hljs-attribute">float</span>:right;<span class="hljs-attribute">bottom</span>:<span class="hljs-number">18px</span>;<span class="hljs-attribute">right</span>:<span class="hljs-number">14px</span>;<span class="hljs-attribute">font-size</span>:<span class="hljs-number">12px</span>;<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#000</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#f5f5f5</span>}<span class="hljs-selector-class">.video-title</span>{<span class="hljs-attribute">font-size</span>:<span class="hljs-number">1.15rem</span>;<span class="hljs-attribute">font-weight</span>:<span class="hljs-number">300</span>}<span class="hljs-selector-class">.images</span>{<span class="hljs-attribute">border-radius</span>:<span class="hljs-number">50%</span>;<span class="hljs-attribute">width</span>:<span class="hljs-number">40px</span>;<span class="hljs-attribute">height</span>:<span class="hljs-number">40px</span>}<span class="hljs-selector-class">.smaller-gray</span>{<span class="hljs-attribute">font-size</span>:.<span class="hljs-number">9rem</span>;<span class="hljs-attribute">color</span>:gray}<span class="hljs-selector-id">#video-below</span>{<span class="hljs-attribute">justify-content</span>:space-between;<span class="hljs-attribute">align-items</span>:center}<span class="hljs-selector-class">.video-section</span>{<span class="hljs-attribute">justify-self</span>:start}<span class="hljs-selector-class">.subscribe-button</span>{<span class="hljs-attribute">float</span>:right;<span class="hljs-attribute">margin-top</span>:-<span class="hljs-number">60px</span>;<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#c00</span>;<span class="hljs-attribute">font-size</span>:smaller;<span class="hljs-attribute">border</span>:none;<span class="hljs-attribute">color</span>:<span class="hljs-number">#fff</span>;<span class="hljs-attribute">padding</span>:<span class="hljs-number">10px</span>}<span class="hljs-selector-class">.align-center</span>{<span class="hljs-attribute">align-items</span>:center;<span class="hljs-attribute">align-content</span>:center;<span class="hljs-attribute">align-self</span>:center}<span class="hljs-selector-class">.inline</span>{<span class="hljs-attribute">display</span>:inline}<span class="hljs-selector-class">.upnext</span>{<span class="hljs-attribute">justify-content</span>:center}<span class="hljs-selector-class">.sidebar-attributes</span>{<span class="hljs-attribute">font-family</span>:Roboto,sans-serif;<span class="hljs-attribute">line-height</span>:<span class="hljs-number">1.2em</span>}<span class="hljs-selector-class">.page-profile</span> <span class="hljs-selector-tag">p</span>{<span class="hljs-attribute">font-size</span>:<span class="hljs-number">14px</span>}<span class="hljs-selector-id">#Squatty-potty</span>{<span class="hljs-attribute">margin-bottom</span>:-<span class="hljs-number">5px</span>;<span class="hljs-attribute">padding-bottom</span>:<span class="hljs-number">5px</span>;<span class="hljs-attribute">margin-top</span>:-<span class="hljs-number">20px</span>}<span class="hljs-selector-id">#avatar</span>{<span class="hljs-attribute">margin-right</span>:<span class="hljs-number">16px</span>;<span class="hljs-attribute">margin-top</span>:-<span class="hljs-number">40px</span>;<span class="hljs-attribute">width</span>:<span class="hljs-number">50px</span>;<span class="hljs-attribute">height</span>:<span class="hljs-number">50px</span>}<span class="hljs-selector-class">.user-name-bolded</span>{<span class="hljs-attribute">margin</span>:<span class="hljs-number">0</span> <span class="hljs-number">10px</span>;<span class="hljs-attribute">font-size</span>:small}<span class="hljs-selector-class">.comment-description</span>{<span class="hljs-attribute">margin-left</span>:<span class="hljs-number">50px</span>;<span class="hljs-attribute">margin-top</span>:-<span class="hljs-number">20px</span>;<span class="hljs-attribute">font-size</span>:smaller}<span class="hljs-selector-class">.smallest-gray</span>{<span class="hljs-attribute">font-size</span>:.<span class="hljs-number">7rem</span>;<span class="hljs-attribute">color</span>:gray}<span class="hljs-selector-class">.reply</span>{<span class="hljs-attribute">margin-left</span>:<span class="hljs-number">10px</span>;<span class="hljs-attribute">font-weight</span>:<span class="hljs-number">300</span>}<span class="hljs-selector-class">.replies</span>{<span class="hljs-attribute">margin-top</span>:<span class="hljs-number">10px</span>}<span class="hljs-selector-class">.gray</span>{<span class="hljs-attribute">color</span>:<span class="hljs-number">#636363</span>}<span class="hljs-selector-class">.sort-button</span>{<span class="hljs-attribute">display</span>:grid;<span class="hljs-attribute">grid-template-columns</span>:<span class="hljs-number">1</span>fr <span class="hljs-number">4.5</span>fr}<span class="hljs-selector-class">.sort-by</span>{<span class="hljs-attribute">margin-left</span>:<span class="hljs-number">10px</span>}<span class="hljs-selector-tag">button</span>{<span class="hljs-attribute">border</span>:none;<span class="hljs-attribute">background-color</span>:transparent}
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>
      <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
      <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Youtube Page<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"left-navbar"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/hamburger_v2ird3.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/youtubelogos_kkvpsz.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"mid-navbar"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"search-bar"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Search"</span> /&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"search-button"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-search"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"right-navbar"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/nav1_ngreqx.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/nav2_zhlzur.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/nav4_oc1mlz.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1638303419/nav3_ayeunv.png"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
    {% for data in items %}
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"d-flex space-between"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-fc d-flex flex-column"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"main-video"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">iframe</span>
              <span class="hljs-attr">width</span>=<span class="hljs-string">"853"</span>
              <span class="hljs-attr">height</span>=<span class="hljs-string">"480"</span>
              <span class="hljs-attr">src</span>=<span class="hljs-string">"https://www.youtube.com/embed/{{videoid}}"</span>
              <span class="hljs-attr">allow</span>=<span class="hljs-string">"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"</span>
              <span class="hljs-attr">allowfullscreen</span>
            &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">iframe</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"video-title"</span>&gt;</span>
              {{data.snippet.title}}
            <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"video-below"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-horizontal"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"video-views"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"smaller-gray"</span>&gt;</span>{{data.statistics.viewCount|intcomma}} views • {{data.snippet.publishedAt|slice:"10"}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-thumbs-up icon-spacing"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span>
                    {{data.statistics.likeCount|intcomma}}<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>
                  &gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-thumbs-down icon-spacing"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span>
                    {{data.statistics.dislikeCount|intcomma}}<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>
                  &gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-share icon-spacing"</span>&gt;</span>SHARE<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-save icon-spacing"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span>
                    SAVE<span class="hljs-tag">&lt;/<span class="hljs-name">i</span>
                  &gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">i</span>
                    <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-ellipsis-h icon-spacing"</span>
                    <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>
                  &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">br</span> /&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-profile"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"user-description"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"subscribe-button"</span>&gt;</span>ALIENX<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>
              {{data.snippet.channelTitle}}
            <span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
              {{data.snippet.description}}
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"video-comments"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"comment-section"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sort-button"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">h6</span>&gt;</span>{{data.statistics.commentCount|intcomma}} Comments<span class="hljs-tag">&lt;/<span class="hljs-name">h6</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                  {% endfor %}
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-sort-amount-down gray"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>

          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><h3 id="heading-template-explanation">Template Explanation.</h3>
<p>In the code above, we start by importing a very important package called <a target="_blank" href="https://docs.djangoproject.com/en/3.2/ref/contrib/humanize/">Django Humanize</a>. This package is useful for adding a “human touch” to data, in our case, changing the data pulled from youtube. The data we want to "humanize" in this case is the counts. You will notice from the API request above, the counts do not have commas, we then add the code below to format the data into commas.</p>
<pre><code><span class="hljs-operator">&lt;</span>i class<span class="hljs-operator">=</span><span class="hljs-string">"fa fa-thumbs-up icon-spacing"</span> aria<span class="hljs-operator">-</span>hidden<span class="hljs-operator">=</span><span class="hljs-string">"true"</span><span class="hljs-operator">&gt;</span>
                    {{data.statistics.likeCount|intcomma}}
<span class="hljs-operator">&lt;</span><span class="hljs-operator">/</span>i<span class="hljs-operator">&gt;</span>
</code></pre><h2 id="heading-testing-our-api">Testing our API</h2>
<p>Make necessary migrations and then run the server. Head over to a youtube video of your choice and remove the HTTPS to HTTP. Remove <a target="_blank" href="www.youtube.com">www.youtube.com</a> to point to your localhost and you should end up with a URL that resembles:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638370515462/FsAQ4SwSOC.png" alt="fff.png" /></p>
<p>If you have any questions, feel free to ask or test my API. Hit a thumbs down, sorry, thumbs up, if you enjoyed this post.</p>
]]></content:encoded></item><item><title><![CDATA[Build an Image Classification API Using Django Rest Framework.]]></title><description><![CDATA[Overview:
Machine Learning (ML) and data science applications are in high demand. When ML algorithms offer information before it is known, the benefits for business are significant. Integrating machine learning algorithms for inference into productio...]]></description><link>https://blog.paulwababu.me.ke/build-an-image-classification-api-using-django-rest-framework</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/build-an-image-classification-api-using-django-rest-framework</guid><category><![CDATA[APIs]]></category><category><![CDATA[Django]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[algorithms]]></category><category><![CDATA[TensorFlow]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Tue, 23 Nov 2021 23:45:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1637580103583/BFl-BE-Uc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-overview">Overview:</h1>
<p>Machine Learning (ML) and data science applications are in high demand. When ML algorithms offer information before it is known, the benefits for business are significant. Integrating machine learning algorithms for inference into production systems is a technological barrier hence the need for deploying ML models as API'S. </p>
<h2 id="heading-introduction">Introduction</h2>
<p>In this short article, we implement AI based models to detect COVID-19 in Chest X-rays and CT Scans using four Deep Learning Algorithms: VGG16, ResNet50, InceptionV3 and Xception. Note, we shall focus mainly on implementing the api and not the model creation. </p>
<p>To test my live endpoint, send a POST request to the following URL with an x-ray image appended to the body of the request. You will get the following sample output if request was successful:</p>
<pre><code><span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/alienx.tech/api</span><span class="hljs-regexp">/v1/xray</span> <span class="hljs-comment"># for the x-ray images</span>
<span class="hljs-symbol">https:</span>/<span class="hljs-regexp">/alienx.tech/api</span><span class="hljs-regexp">/v1/ct</span> <span class="hljs-comment"># for CT scans</span>
</code></pre><pre><code>{
    <span class="hljs-attr">"status"</span>: <span class="hljs-string">"success"</span>,
    <span class="hljs-attr">"data"</span>: {
        <span class="hljs-attr">"asset_id"</span>: <span class="hljs-string">"3e978ba830fb266978af20f2bf816f5e"</span>,
        <span class="hljs-attr">"public_id"</span>: <span class="hljs-string">"vacpxfywfohgfprwhrso"</span>,
        <span class="hljs-attr">"version"</span>: <span class="hljs-number">1637699139</span>,
        <span class="hljs-attr">"version_id"</span>: <span class="hljs-string">"c9017c7d3b28ce797edefec0b0d72796"</span>,
        <span class="hljs-attr">"signature"</span>: <span class="hljs-string">"e9c632b832e773cbbcb8906f93aba1d9e859d4bf"</span>,
        <span class="hljs-attr">"width"</span>: <span class="hljs-number">1205</span>,
        <span class="hljs-attr">"height"</span>: <span class="hljs-number">1395</span>,
        <span class="hljs-attr">"format"</span>: <span class="hljs-string">"png"</span>,
        <span class="hljs-attr">"resource_type"</span>: <span class="hljs-string">"image"</span>,
        <span class="hljs-attr">"created_at"</span>: <span class="hljs-string">"2021-11-23T20:25:39Z"</span>,
        <span class="hljs-attr">"tags"</span>: [],
        <span class="hljs-attr">"bytes"</span>: <span class="hljs-number">1325222</span>,
        <span class="hljs-attr">"type"</span>: <span class="hljs-string">"upload"</span>,
        <span class="hljs-attr">"etag"</span>: <span class="hljs-string">"86005d3c34202b10949db5569570cd16"</span>,
        <span class="hljs-attr">"placeholder"</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">"url"</span>: <span class="hljs-string">"http://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png"</span>,
        <span class="hljs-attr">"secure_url"</span>: <span class="hljs-string">"https://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png"</span>,
        <span class="hljs-attr">"original_filename"</span>: <span class="hljs-string">"covid-19-pneumonia-22"</span>,
        <span class="hljs-attr">"api_key"</span>: <span class="hljs-string">"138196782467569"</span>
    },
    <span class="hljs-attr">"url"</span>: <span class="hljs-string">"http://res.cloudinary.com/prometheusapi/image/upload/v1637699139/vacpxfywfohgfprwhrso.png"</span>,
    <span class="hljs-attr">"xception_chest_pred"</span>: <span class="hljs-string">"100.00% COVID"</span>,
    <span class="hljs-attr">"inception_chest_pred"</span>: <span class="hljs-string">"100.00% COVID"</span>,
    <span class="hljs-attr">"vgg_chest_pred"</span>: <span class="hljs-string">"100.00% COVID"</span>,
    <span class="hljs-attr">"resnet_chest_pred"</span>: <span class="hljs-string">"100.00% COVID"</span>
}
</code></pre><h2 id="heading-ml-model-building">ML Model Building</h2>
<p>The dataset for the project was gathered from two open source Github repositories:</p>
<ul>
<li>Chest X-ray images (1000 images) were obtained from: https://github.com/ieee8023/covid-chestxray-dataset</li>
<li>CT Scan images (750 images) were obtained from: https://github.com/UCSD-AI4H/COVID-CT/tree/master/Data-split</li>
</ul>
<p>Four algorithms: VGG16, ResNet50, InceptionV3 and Xception were trained separately on Chest X-rays and CT Scans, giving us a total of 8 deep learning models. 80% of the images were used for training the models and the remaining 20% for testing the accuracy of the models.</p>
<p>The code for training the 8 models is available on the creators <a target="_blank" href="https://github.com/kaushikjadhav01/COVID-19-Detection-Flask-App-based-on-Chest-X-rays-and-CT-Scans">github</a> or my <a target="_blank" href="https://github.com/paulwababu/Django-Covid-19-Detector-API">repository</a>. The model for the project can be found on the following google <a target="_blank" href="https://drive.google.com/file/d/1dA-rdmDmCGa3xxW5KpfLJdo7M54lPcQq/view">drive</a>.</p>
<h2 id="heading-turning-the-model-into-an-restful-api">Turning the Model into an RESTFUL API</h2>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip install django requests djangorestframework tensorflow cloudinary opencv-python
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests djangorestframework tensorflow cloudinary opencv-python
</code></pre><h2 id="heading-setting-up-your-django-application">Setting Up Your Django Application</h2>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp/
    manage.py
    mainapp/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp monitor
</code></pre><p>This will create the following:</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code>INSTALLED_APPS = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'rest_framework'</span>,#<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
    <span class="hljs-string">'monitor'</span>, #<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
]
</code></pre><p>Ensure you are in the monitor directory then create a new directory called templates and a new file called urls.py. Your directory structure of monitor application should look like this</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
    templates/
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our monitor app URL to include the URLs we shall create next on the monitor app:</p>
<pre><code><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> <span class="hljs-keyword">admin</span>
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>

urlpatterns = [
    #path(<span class="hljs-string">'admin/'</span>, <span class="hljs-keyword">admin</span>.site.urls),
    path(<span class="hljs-string">''</span>, <span class="hljs-keyword">include</span>(<span class="hljs-string">'monitor.urls'</span>)),#monitor app url
]
</code></pre><p>Now, on the monitor/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>
<span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> *

urlpatterns = [
    path(<span class="hljs-string">'api/upload/xray'</span>, UploadView.as_view(), <span class="hljs-type">name</span> = <span class="hljs-string">'prediction'</span>),
    path(<span class="hljs-string">'api/upload/ct'</span>, CTUploadView.as_view(), <span class="hljs-type">name</span> = <span class="hljs-string">'ct_prediction'</span>),
]
</code></pre><p>Let’s create another directory to store our machine learning model. I’ll also add the dataset to the project for those who want to achieve the whole dataset. (It is not compulsory to create a data folder.)</p>
<pre><code>(venv)$ <span class="hljs-keyword">mkdir</span> ml
(venv)$ <span class="hljs-keyword">mkdir</span> ml/models
(venv)$ <span class="hljs-keyword">mkdir</span> ml/data
</code></pre><p>We also need to tell Django where our machine learning model is located and also add our cloudinary configuration there. Add these lines to settings.py file:</p>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> cloudinary

cloudinary.config( 
  cloud_name = "prometheusapi", 
  api_key = "GETYOURAPIKEY", 
  api_secret = "GETYOURAPIKEY" 
)

MODELS = os.path.<span class="hljs-keyword">join</span>(BASE_DIR, <span class="hljs-string">'ml/models'</span>)
</code></pre><h2 id="heading-load-keras-model-through-appspy">Load Keras Model through apps.py</h2>
<p>Load your machine learning models in apps.py so that when the application starts, the trained model is loaded only once. Otherwise, the trained model is loaded each time an endpoint is called, and then the response time will be slower. </p>
<p>Let’s update apps.py</p>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> django.apps <span class="hljs-keyword">import</span> AppConfig
<span class="hljs-keyword">from</span> django.conf <span class="hljs-keyword">import</span> settings
<span class="hljs-keyword">from</span> tensorflow.keras.models <span class="hljs-keyword">import</span> load_model
<span class="hljs-keyword">from</span> tensorflow <span class="hljs-keyword">import</span> keras


<span class="hljs-keyword">class</span> ResNetModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'resnetAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "resnet_chest.h5")
    model = keras.models.load_model(MODEL_FILE)

<span class="hljs-keyword">class</span> ResNetCTModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'resnetCTAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "resnet_ct.h5")
    model = keras.models.load_model(MODEL_FILE)

<span class="hljs-keyword">class</span> VGGModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'vggAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "vgg_chest.h5")
    model = keras.models.load_model(MODEL_FILE)

<span class="hljs-keyword">class</span> VGGCTModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'vggCTAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "vgg_ct.h5")
    model = keras.models.load_model(MODEL_FILE)    

<span class="hljs-keyword">class</span> InceptionModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'inceptionv3_chestAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "inceptionv3_chest.h5")    
    model = keras.models.load_model(MODEL_FILE)

<span class="hljs-keyword">class</span> InceptionCTModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'inceptionv3_chestCTAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "inception_ct.h5")    
    model = keras.models.load_model(MODEL_FILE)    

<span class="hljs-keyword">class</span> ExceptionModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'xception_chestAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "xception_chest.h5")    
    model = keras.models.load_model(MODEL_FILE)

<span class="hljs-keyword">class</span> ExceptionCTModelConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'xception_chestCTAPI'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "xception_ct.h5")    
    model = keras.models.load_model(MODEL_FILE)
</code></pre><h2 id="heading-edit-viewspy">Edit views.py</h2>
<p>The last step is to update views.py. The views will be mainly responsible for two tasks:</p>
<ul>
<li>Process incoming POST requests.</li>
<li>Make a prediction with the incoming data and give the result as a Response.</li>
</ul>
<pre><code><span class="hljs-keyword">import</span> urllib
<span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> .apps <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">from</span> rest_framework.views <span class="hljs-keyword">import</span> APIView
<span class="hljs-keyword">from</span> rest_framework.response <span class="hljs-keyword">import</span> Response
<span class="hljs-keyword">from</span> rest_framework.parsers <span class="hljs-keyword">import</span> MultiPartParser, JSONParser
<span class="hljs-keyword">import</span> cloudinary.uploader
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> cv2

<span class="hljs-comment"># Create your views here.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UploadView</span>(<span class="hljs-params">APIView</span>):</span>
    parser_classes = (
        MultiPartParser,
        JSONParser,
    )

<span class="hljs-meta">    @staticmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post</span>(<span class="hljs-params">request</span>):</span>
        file = request.data.get(<span class="hljs-string">'picture'</span>)
        upload_data = cloudinary.uploader.upload(file)
        <span class="hljs-comment">#print(upload_data)</span>
        img = upload_data[<span class="hljs-string">'url'</span>]


        <span class="hljs-comment">#load models</span>
        resnet_chest = ResNetModelConfig.model
        vgg_chest = VGGModelConfig.model
        inception_chest = InceptionModelConfig.model
        xception_chest = ExceptionModelConfig.model

        req = urllib.request.urlopen(img)
        arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
        image = cv2.imdecode(arr, <span class="hljs-number">-1</span>) <span class="hljs-comment"># 'Load it as it is'</span>
        <span class="hljs-comment">#image = cv2.imread('upload_chest.jpg') # read file </span>
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) <span class="hljs-comment"># arrange format as per keras</span>
        image = cv2.resize(image,(<span class="hljs-number">224</span>,<span class="hljs-number">224</span>))
        image = np.array(image) / <span class="hljs-number">255</span>
        image = np.expand_dims(image, axis=<span class="hljs-number">0</span>)

        resnet_pred = resnet_chest.predict(image)
        probability = resnet_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Resnet Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            resnet_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            resnet_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(resnet_chest_pred)</span>

        vgg_pred = vgg_chest.predict(image)
        probability = vgg_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("VGG Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            vgg_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            vgg_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(vgg_chest_pred)</span>

        inception_pred = inception_chest.predict(image)
        probability = inception_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Inception Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            inception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            inception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(inception_chest_pred)</span>

        xception_pred = xception_chest.predict(image)
        probability = xception_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Xception Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            xception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            xception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(xception_chest_pred)</span>
        <span class="hljs-keyword">return</span> Response({
            <span class="hljs-string">'status'</span>: <span class="hljs-string">'success'</span>,
            <span class="hljs-string">'data'</span>: upload_data,
            <span class="hljs-string">'url'</span>:img,
            <span class="hljs-string">'xception_chest_pred'</span>:xception_chest_pred,
            <span class="hljs-string">'inception_chest_pred'</span>:inception_chest_pred,
            <span class="hljs-string">'vgg_chest_pred'</span>:vgg_chest_pred,
            <span class="hljs-string">'resnet_chest_pred'</span>:resnet_chest_pred,
        }, status=<span class="hljs-number">201</span>)


<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CTUploadView</span>(<span class="hljs-params">APIView</span>):</span>
    parser_classes = (
        MultiPartParser,
        JSONParser,
    )

<span class="hljs-meta">    @staticmethod</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">post</span>(<span class="hljs-params">request</span>):</span>
        file = request.data.get(<span class="hljs-string">'picture'</span>)
        upload_data = cloudinary.uploader.upload(file)
        <span class="hljs-comment">#print(upload_data)</span>
        img = upload_data[<span class="hljs-string">'url'</span>]


        <span class="hljs-comment">#load models</span>
        resnet_chest = ResNetCTModelConfig.model
        vgg_chest = VGGCTModelConfig.model
        inception_chest = InceptionCTModelConfig.model
        xception_chest = ExceptionCTModelConfig.model

        req = urllib.request.urlopen(img)
        arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
        image = cv2.imdecode(arr, <span class="hljs-number">-1</span>) <span class="hljs-comment"># 'Load it as it is'</span>
        <span class="hljs-comment">#image = cv2.imread('upload_chest.jpg') # read file </span>
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) <span class="hljs-comment"># arrange format as per keras</span>
        image = cv2.resize(image,(<span class="hljs-number">224</span>,<span class="hljs-number">224</span>))
        image = np.array(image) / <span class="hljs-number">255</span>
        image = np.expand_dims(image, axis=<span class="hljs-number">0</span>)

        resnet_pred = resnet_chest.predict(image)
        probability = resnet_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Resnet Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            resnet_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            resnet_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(resnet_chest_pred)</span>

        vgg_pred = vgg_chest.predict(image)
        probability = vgg_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("VGG Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            vgg_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            vgg_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(vgg_chest_pred)</span>

        inception_pred = inception_chest.predict(image)
        probability = inception_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Inception Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            inception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            inception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(inception_chest_pred)</span>

        xception_pred = xception_chest.predict(image)
        probability = xception_pred[<span class="hljs-number">0</span>]
        <span class="hljs-comment">#print("Xception Predictions:")</span>
        <span class="hljs-keyword">if</span> probability[<span class="hljs-number">0</span>] &gt; <span class="hljs-number">0.5</span>:
            xception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % (probability[<span class="hljs-number">0</span>]*<span class="hljs-number">100</span>) + <span class="hljs-string">'% COVID'</span>) 
        <span class="hljs-keyword">else</span>:
            xception_chest_pred = str(<span class="hljs-string">'%.2f'</span> % ((<span class="hljs-number">1</span>-probability[<span class="hljs-number">0</span>])*<span class="hljs-number">100</span>) + <span class="hljs-string">'% NonCOVID'</span>)
        <span class="hljs-comment">#print(xception_chest_pred)</span>
        <span class="hljs-keyword">return</span> Response({
            <span class="hljs-string">'status'</span>: <span class="hljs-string">'success'</span>,
            <span class="hljs-string">'data'</span>: upload_data,
            <span class="hljs-string">'url'</span>:img,
            <span class="hljs-string">'xceptionCT_chest_pred'</span>:xception_chest_pred,
            <span class="hljs-string">'inceptionCT_chest_pred'</span>:inception_chest_pred,
            <span class="hljs-string">'vggCT_chest_pred'</span>:vgg_chest_pred,
            <span class="hljs-string">'resnetCT_chest_pred'</span>:resnet_chest_pred,
        }, status=<span class="hljs-number">201</span>)
</code></pre><h2 id="heading-testing-our-api">Testing our API</h2>
<p>Create the necessary migrations then run the server:</p>
<pre><code>(myenv) $ python manage.py makemigrations
(myenv) $ python manage.py migrate
(myenv) $ python manage.py runserver
</code></pre><p>Fire up Postman and make a POST request with an image appended to the body.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637710271371/fsrLdJHEA.png" alt="polo.png" /></p>
<h3 id="heading-thanks-for-staying-tuned">Thanks for staying tuned!</h3>
]]></content:encoded></item><item><title><![CDATA[Develop a Spam Filtering Model in Python & Deploy it with Django]]></title><description><![CDATA[Introduction
Spam is a fact of life on the internet. If you enable comments or contact sections on your website, you will have to deal with spammers. To prevent your site from making a poor first impression, you’ll need to find a way to stop spam in ...]]></description><link>https://blog.paulwababu.me.ke/develop-a-spam-filtering-model-in-python-and-deploy-it-with-django</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/develop-a-spam-filtering-model-in-python-and-deploy-it-with-django</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[Django]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[algorithms]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Wed, 17 Nov 2021 15:30:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636892198346/1BiJqpgrc.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Spam is a fact of life on the internet. If you enable comments or contact sections on your website, you will have to deal with spammers. To prevent your site from making a poor first impression, you’ll need to find a way to stop spam in its tracks. This is especially important if you are developing a website without a content management system like Wordpress as they come bundled with spam filtering plugins. You could also use an API like <a target="_blank" href="https://akismet.com/">Akismet</a>, however this comes at a cost, which can be avoided by implementing a relatively accurate model of your own.</p>
<p>Kaggle and other data science bootcamps are great for learning how to build and optimize models, but they don’t teach you how to actually use this models in real world scenarios, where there’s a major difference between building a model, and deploying it to be used by end users on the internet. </p>
<p>In this tutorial, you’re going to build an SMS spam detection web application. This application will be built in Python using the Django framework, and will include a deep learning model that you will train to detect SMS spam by leveraging the Naive Bayes theorem. </p>
<h2 id="heading-naive-bayes-classification">Naive Bayes classification</h2>
<p>The classification of Naive Bayes is a simple probability algorithm based on the fact that all model characteristics are independent. We assume that every word in the message is independent of all other words in the context of the spam filters, and we count them with the ignorance of the context.</p>
<p>By the state of the current set of terms, our classification algorithm generates probabilities of the message to be spam or not spam. The probability estimation is based on the Bayes formula, and the formula components are determined on the basis of the word frequencies in the whole message package.</p>
<h2 id="heading-model-building">Model Building</h2>
<p>The data is a collection of SMS messages tagged as spam or ham that can be found <a target="_blank" href="https://raw.githubusercontent.com/paulwababu/datasets/main/spam.csv">here</a>. First, we will use this dataset to build a prediction model that will accurately classify which texts are spam and which are not, then save the model to be used later for predictions.</p>
<h2 id="heading-exploration-of-dataset">Exploration of dataset</h2>
<p>The first thing that should be done is to import dependencies. If you do not have the libraries installed, kindly do so before proceeding.</p>
<pre><code><span class="hljs-keyword">import</span> pandas as pd
<span class="hljs-keyword">import</span> numpy as np
from sklearn.feature_extraction.text <span class="hljs-keyword">import</span> CountVectorizer
from sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
from sklearn.naive_bayes <span class="hljs-keyword">import</span> MultinomialNB
from sklearn.metrics <span class="hljs-keyword">import</span> classification_report
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">import</span> pickle
</code></pre><p>Next, we load the dataset using pandas:</p>
<pre><code>df = pd.read_csv(<span class="hljs-string">'https://raw.githubusercontent.com/paulwababu/datasets/main/spam.csv'</span>, encoding = <span class="hljs-string">'latin-1'</span>)
print(df.head())
</code></pre><p>Drop the unwanted columns, like so:</p>
<pre><code>df.<span class="hljs-keyword">drop</span>([<span class="hljs-string">'Unnamed: 2'</span>, <span class="hljs-string">'Unnamed: 3'</span>, <span class="hljs-string">'Unnamed: 4'</span>], axis=<span class="hljs-number">1</span>, inplace=<span class="hljs-keyword">True</span>)
</code></pre><p>We have to convert the non-numerical column 'spam' and 'ham' into numerical values using pandas map() function</p>
<pre><code>df[<span class="hljs-string">'label'</span>] = df[<span class="hljs-string">'v1'</span>].<span class="hljs-keyword">map</span>({<span class="hljs-string">'ham'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'spam'</span>: <span class="hljs-number">1</span>})
</code></pre><p>Then we have to separate the feature columns(independent variables) from the target column(dependent variable).</p>
<p>The feature columns are the columns that we try to predict from, and the target column is the column with the values we try to predict.</p>
<pre><code><span class="hljs-attr">X</span> = df[<span class="hljs-string">'v2'</span>] 
<span class="hljs-attr">y</span> = df[<span class="hljs-string">'label'</span>]
</code></pre><h2 id="heading-ml-model-building">ML Model Building</h2>
<p>Let us now proceed to building our actual model. </p>
<pre><code>cv = CountVectorizer()
X = cv.fit_transform(X) 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
model = MultinomialNB()
model.fit(X_train,y_train)
<span class="hljs-comment">#model.score(X_test,y_test)</span>
y_pred = model.predict(X_test)
print(classification_report(y_test, y_pred))
</code></pre><pre><code>              <span class="hljs-attribute">precision</span>    recall  f<span class="hljs-number">1</span>-score   support

           <span class="hljs-attribute">0</span>       <span class="hljs-number">0</span>.<span class="hljs-number">99</span>      <span class="hljs-number">0</span>.<span class="hljs-number">99</span>      <span class="hljs-number">0</span>.<span class="hljs-number">99</span>      <span class="hljs-number">1587</span>
           <span class="hljs-attribute">1</span>       <span class="hljs-number">0</span>.<span class="hljs-number">93</span>      <span class="hljs-number">0</span>.<span class="hljs-number">92</span>      <span class="hljs-number">0</span>.<span class="hljs-number">92</span>       <span class="hljs-number">252</span>

    <span class="hljs-attribute">accuracy</span>                           <span class="hljs-number">0</span>.<span class="hljs-number">98</span>      <span class="hljs-number">1839</span>
   <span class="hljs-attribute">macro</span> avg       <span class="hljs-number">0</span>.<span class="hljs-number">96</span>      <span class="hljs-number">0</span>.<span class="hljs-number">95</span>      <span class="hljs-number">0</span>.<span class="hljs-number">96</span>      <span class="hljs-number">1839</span>
<span class="hljs-attribute">weighted</span> avg       <span class="hljs-number">0</span>.<span class="hljs-number">98</span>      <span class="hljs-number">0</span>.<span class="hljs-number">98</span>      <span class="hljs-number">0</span>.<span class="hljs-number">98</span>      <span class="hljs-number">1839</span>
</code></pre><p>Not only Naive Bayes classifier easy to implement but also provides very good result. </p>
<p>In the code above, we create a vectorize function that transforms a given text into a vector on the basis of the frequency (count) of each word that occurs in the entire text. We then proceed to splitting the data into train and test variables which we use to get the classification report of the model. We then call the multinomial Naive Bayes model which is suitable for classification with discrete features (e.g., word counts for text classification)</p>
<h2 id="heading-model-and-vectorizer-persistence">Model and Vectorizer Persistence.</h2>
<p>After training the model, we should to have a way to persist the model for future use without having to retrain. To achieve this, need to save the model for the later use. Add the following lines of code:</p>
<pre><code><span class="hljs-comment"># Save the model</span>
joblib_file = <span class="hljs-string">"MultinomialNaiveBayesModel.joblib"</span>
joblib.dump(model, joblib_file)
</code></pre><p>We also need to save the vectorize function that we created earlier otherwise you throw it away because a vectorizer once created, doesn't exist past the lifetime of your vectorize function.</p>
<pre><code><span class="hljs-comment"># Save the vectorizer</span>
vec_file = <span class="hljs-string">'MultinomialNaiveBayesModelVectorizer.pickle'</span>
pickle.dump(cv, <span class="hljs-keyword">open</span>(vec_file, <span class="hljs-string">'wb'</span>))
</code></pre><p>If we intend to retrain the model, we can use the partial_fit function in order to keep improving the model incase of model degradation over time. I will post a blog later that addresses how to identify and correct <a target="_blank" href="https://www.section.io/engineering-education/correcting-data-shift/#:~:text=Prior%20probability%20shift%20is%20characterized,the%20reverse%20of%20covariate%20shift.&amp;text=If%20the%20prior%20probabilities%20are,50%25%20non%2Dspam%20mail.">dataset shift in machine learning</a> </p>
<h2 id="heading-turning-the-spam-message-classifier-into-a-django-web-application">Turning the Spam Message Classifier into a Django Web Application</h2>
<p>Having trained and saved the model for classifying SMS messages in the previous section, we will develop a web application that consists of a simple web page with a form field that lets us enter a message. After submitting the message to the web application, it will render it on a new page which gives us a result of spam or not spam.</p>
<p>Below is snapshot of the final implementation</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637150283253/YWtssz89w.png" alt="CfyuGX7l5aBe6TuCx-PjciFKywPM_rAAmOCaJcTuStURvV.width-800.png" /></p>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip install django requests numpy joblib scikit-learn
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests numpy joblib scikit-learn
</code></pre><h2 id="heading-setting-up-your-django-application">Setting Up Your Django Application</h2>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp/
    manage.py
    mainapp/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp monitor
</code></pre><p>This will create the following:</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code><span class="hljs-attr">INSTALLED_APPS</span> = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'monitor'</span>, <span class="hljs-comment">#new line</span>
]
</code></pre><p>Ensure you are in the monitor directory then create a new directory called templates then a new file called urls.py. Your directory structure of monitor application should look like this</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
    templates/
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our monitor app URL to include the URLs we shall create next on the monitor app:</p>
<pre><code><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> <span class="hljs-keyword">admin</span>
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>

urlpatterns = [
    #path(<span class="hljs-string">'admin/'</span>, <span class="hljs-keyword">admin</span>.site.urls),
    path(<span class="hljs-string">''</span>, <span class="hljs-keyword">include</span>(<span class="hljs-string">'monitor.urls'</span>)),#monitor app url
]
</code></pre><p>Now, on the monitor/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>
<span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> *

urlpatterns = [
    path(<span class="hljs-string">''</span>, views.sms, <span class="hljs-type">name</span> = <span class="hljs-string">'sms'</span>),
    path(<span class="hljs-string">'inbox/'</span>, views.inbox, <span class="hljs-type">name</span>=<span class="hljs-string">'inbox'</span>)
]
</code></pre><p>Let’s create another directory to store our machine learning model. I’ll also add the dataset to the project for those who want to achieve the whole dataset. (It is not compulsory to create a data folder.) Be sure to move the vectorizer file and the joblib file we created earlier to ml/model folder</p>
<pre><code>(venv)$ <span class="hljs-keyword">mkdir</span> ml
(venv)$ <span class="hljs-keyword">mkdir</span> ml/models
(venv)$ <span class="hljs-keyword">mkdir</span> ml/data
</code></pre><p>We also need to tell Django where our machine learning model and our vectorizer file is located. Add these lines to settings.py file:</p>
<pre><code><span class="hljs-keyword">import</span> os
MODELS = os.path.<span class="hljs-keyword">join</span>(BASE_DIR, <span class="hljs-string">'ml/models'</span>)
</code></pre><h2 id="heading-load-model-and-vectorizer-through-appspy">Load Model and Vectorizer through apps.py</h2>
<p>Load your machine learning models and your vectorizer in apps.py so that when the application starts, the trained model is loaded only once. Otherwise, the trained model is loaded each time an endpoint is called, and then the response time will be slower. </p>
<p>Let’s update apps.py</p>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">from</span> django.apps <span class="hljs-keyword">import</span> AppConfig
<span class="hljs-keyword">from</span> django.conf <span class="hljs-keyword">import</span> settings


<span class="hljs-keyword">class</span> ApiConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'api'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "MultinomialNaiveBayesModel.joblib")
    model = joblib.<span class="hljs-keyword">load</span>(MODEL_FILE)

<span class="hljs-keyword">class</span> VectorizerConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'api2'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "MultinomialNaiveBayesModelVectorizer.pickle")
    model = joblib.<span class="hljs-keyword">load</span>(MODEL_FILE)
</code></pre><h2 id="heading-edit-modelspy">Edit models.py</h2>
<p>Create our database models which we shall use to store our classified models. On the monitor/models.py file:</p>
<pre><code><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-comment"># Create your models here.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Monitor2</span>(<span class="hljs-params">models.Model</span>):</span>
    message = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    SPAM = <span class="hljs-number">1</span>
    HAM = <span class="hljs-number">0</span>
    IS_SPAM_OR_NAH = [(SPAM, <span class="hljs-string">'spam'</span>), (HAM, <span class="hljs-string">'not_spam'</span>)]
    messageClassified = models.IntegerField(choices=IS_SPAM_OR_NAH, null=<span class="hljs-literal">True</span>)
    contact = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
</code></pre><h2 id="heading-edit-viewspy">Edit views.py</h2>
<p>The views will be mainly responsible for two tasks:</p>
<ul>
<li>Process incoming POST requests.</li>
<li>Make a prediction with the incoming data and give the result as a Response.</li>
<li>Display the classified text into a HTML template.</li>
</ul>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> *
<span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, redirect


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sms</span>(<span class="hljs-params">request</span>):</span>
    <span class="hljs-keyword">if</span> request.method == <span class="hljs-string">'POST'</span>:
        number = request.POST[<span class="hljs-string">'contact'</span>]
        message = request.POST[<span class="hljs-string">'message'</span>]
<span class="hljs-comment"># datetime object containing current date and time</span>
        now = datetime.now()    
        now = now.strftime(<span class="hljs-string">"%d/%m/%Y %H:%M:%S"</span>)

        naiveModel = ApiConfig.model
        naiveVect = VectorizerConfig.model
        convertString = str(message)
        message = convertString
        data = [message]
        vect = naiveVect.transform(data).toarray()
        my_prediction = naiveModel.predict(vect)
        print(my_prediction)
        saveNow = Monitor2(
            message=message,
            messageClassified=my_prediction,
            contact=number
        )
        saveNow.save()
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'sms.html'</span>)

<span class="hljs-comment">#inbox view</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">inbox</span>(<span class="hljs-params">request</span>):</span>
    dataSaved = Monitor2.objects.all()
    data = {
        <span class="hljs-string">"dataSaved"</span>: dataSaved,
    }
    print(data)
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'inbox.html'</span>, data)
</code></pre><p>On the monitor/templates folder, create sms.html and inbox.html web page and add the lines below:</p>
<p>monitor/templates/sms.html file:</p>
<pre><code><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Document<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"myform"</span> <span class="hljs-attr">method</span>=<span class="hljs-string">"POST"</span>&gt;</span>
        {% csrf_token %}
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-6 form-group"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name1"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control p-4"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your Name"</span> <span class="hljs-attr">required</span>=<span class="hljs-string">"required"</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-6 form-group"</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"contact"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control p-4"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Your Contact"</span> <span class="hljs-attr">required</span>=<span class="hljs-string">"required"</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-group"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control py-3 px-4"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"message"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">"5"</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Message"</span> <span class="hljs-attr">required</span>=<span class="hljs-string">"required"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary py-3 px-5"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Send Message<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>monitor/templates/inbox.html file:</p>
<pre><code><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
<span class="hljs-selector-tag">table</span>, <span class="hljs-selector-tag">th</span>, <span class="hljs-selector-tag">td</span> {
  <span class="hljs-attribute">border</span>:<span class="hljs-number">1px</span> solid black;
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A basic HTML table<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"width:100%"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>#<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>From<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Body<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Classification<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
  {% for x in dataSaved %}
  <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ loop.index }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ x.contact }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ x.message }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      {% if x.messageClassified == 1 %}
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Spam<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      {% else %}
      <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>Non Spam<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
      {% endif %}
  <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
  {% endfor %}
<span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>Make the necessary migrations like so:</p>
<pre><code>(myenv) $ python manage.py makemigrations
(myenv) $ python manage.py migrate
(myenv) $ python manage.py runserver
</code></pre><h2 id="heading-testing-if-it-works">Testing if it works!</h2>
<p>Head over http://127.0.0.1:8000 and complete the form with both spam and non spam</p>
<p>Proceed to http://127.0.0.1:8000/inbox to check out the classified data! Below is a snapshot of my implementation, sorry I couldn't make the CSS;(</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637159575230/G4Yj5QNXf.png" alt="Screenshot from 2021-11-17 17-32-30.png" /></p>
<h3 id="heading-thanks-for-staying-tuned">Thanks for staying tuned!</h3>
]]></content:encoded></item><item><title><![CDATA[Build a Machine Learning API With Django Rest Framework]]></title><description><![CDATA[Introduction
Finding the proper treatment, especially drug treatment, can be a difficult task. Whether you're looking for drugs to treat seasonal allergies, or you're treating a serious illness, collecting data on various aspects of patients and what...]]></description><link>https://blog.paulwababu.me.ke/build-a-machine-learning-api-with-django-rest-framework</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/build-a-machine-learning-api-with-django-rest-framework</guid><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[Django]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Web Development]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Wed, 10 Nov 2021 10:41:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1636517220013/YDJ9DyMOe.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>Finding the proper treatment, especially drug treatment, can be a difficult task. Whether you're looking for drugs to treat seasonal allergies, or you're treating a serious illness, collecting data on various aspects of patients and what treatments they best respond to can be vital for saving lives and increasing patient convenience. Here, we'll act as a data analyst compiling medical data on a set of patients all suffering from the same illness. During their treatment, each patient responded to one of five drug treatments</p>
<p>In this article, we'll:</p>
<ul>
<li>Build a simple Decision Tree model to predict Drug Treatment with relatively high accuracy.</li>
<li>Create an API with <a target="_blank" href="https://www.django-rest-framework.org/">Django Rest Framework</a> that will be used to consume the Decision Tree Model created.</li>
</ul>
<h2 id="heading-build-a-model">Build a Model</h2>
<p>Let us start by building and saving a machine learning model that will be later used to make predictions for our API.</p>
<h3 id="heading-dataset">Dataset</h3>
<p>Find the dataset for this model on my <a target="_blank" href="https://raw.githubusercontent.com/paulwababu/datasets/main/drug200.csv">Github repo</a>. The file is a CSV with data from different patients who received treatment for the same disease. The different drugs can be drugA, drugB, drugC, drugX, or drugY.</p>
<p>Let’s get started with the exploration of the dataset.</p>
<p>The first thing that should be done is to import dependencies. If you do not have the libraries installed, kindly do so before proceeding. </p>
<pre><code><span class="hljs-keyword">import</span> pandas
from sklearn <span class="hljs-keyword">import</span> tree
<span class="hljs-keyword">import</span> pydotplus
from sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeClassifier
<span class="hljs-keyword">import</span> matplotlib.pyplot as plt
<span class="hljs-keyword">import</span> matplotlib.image as pltimg
from sklearn.metrics <span class="hljs-keyword">import</span> classification_report, plot_confusion_matrix, plot_roc_curve
from sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
from sklearn.preprocessing <span class="hljs-keyword">import</span> StandardScaler
<span class="hljs-keyword">import</span> joblib
</code></pre><p>Next, we load the dataset using pandas:</p>
<pre><code>df <span class="hljs-operator">=</span> pandas.read_csv(<span class="hljs-string">"https://raw.githubusercontent.com/paulwababu/datasets/main/drug200.csv"</span>)
print(df.head())
</code></pre><pre><code>   <span class="hljs-attribute">Age</span> Sex      BP Cholesterol  Na_to_K   Drug
<span class="hljs-attribute">0</span>   <span class="hljs-number">23</span>   F    HIGH        HIGH   <span class="hljs-number">25</span>.<span class="hljs-number">355</span>  drugY
<span class="hljs-attribute">1</span>   <span class="hljs-number">47</span>   M     LOW        HIGH   <span class="hljs-number">13</span>.<span class="hljs-number">093</span>  drugC
<span class="hljs-attribute">2</span>   <span class="hljs-number">47</span>   M     LOW        HIGH   <span class="hljs-number">10</span>.<span class="hljs-number">114</span>  drugC
<span class="hljs-attribute">3</span>   <span class="hljs-number">28</span>   F  NORMAL        HIGH    <span class="hljs-number">7</span>.<span class="hljs-number">798</span>  drugX
<span class="hljs-attribute">4</span>   <span class="hljs-number">61</span>   F     LOW        HIGH   <span class="hljs-number">18</span>.<span class="hljs-number">043</span>  drugY
</code></pre><p>To make a decision tree, all data has to be numerical.</p>
<p>We have to convert the non-numerical columns 'Gender', 'Cholesterol', and 'BP' into numerical values.</p>
<p>Pandas have a map() method that takes a dictionary with information on how to convert the values.</p>
<pre><code>#Change <span class="hljs-keyword">string</span> values into numerical values:
d = {<span class="hljs-string">'M'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'F'</span>: <span class="hljs-number">0</span>}
df[<span class="hljs-string">'Sex'</span>] = df[<span class="hljs-string">'Sex'</span>].<span class="hljs-keyword">map</span>(d)

d = {<span class="hljs-string">'HIGH'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'LOW'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'NORMAL'</span>: <span class="hljs-number">2</span>}
df[<span class="hljs-string">'BP'</span>] = df[<span class="hljs-string">'BP'</span>].<span class="hljs-keyword">map</span>(d)

d = {<span class="hljs-string">'HIGH'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'LOW'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'NORMAL'</span>: <span class="hljs-number">2</span>}
df[<span class="hljs-string">'Cholesterol'</span>] = df[<span class="hljs-string">'Cholesterol'</span>].<span class="hljs-keyword">map</span>(d)
<span class="hljs-built_in">print</span>(df.head())
</code></pre><pre><code>   <span class="hljs-attribute">Age</span>  Sex  BP  Cholesterol  Na_to_K   Drug
<span class="hljs-attribute">0</span>   <span class="hljs-number">23</span>    <span class="hljs-number">0</span>   <span class="hljs-number">0</span>            <span class="hljs-number">0</span>   <span class="hljs-number">25</span>.<span class="hljs-number">355</span>  drugY
<span class="hljs-attribute">1</span>   <span class="hljs-number">47</span>    <span class="hljs-number">1</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">13</span>.<span class="hljs-number">093</span>  drugC
<span class="hljs-attribute">2</span>   <span class="hljs-number">47</span>    <span class="hljs-number">1</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">10</span>.<span class="hljs-number">114</span>  drugC
<span class="hljs-attribute">3</span>   <span class="hljs-number">28</span>    <span class="hljs-number">0</span>   <span class="hljs-number">2</span>            <span class="hljs-number">0</span>    <span class="hljs-number">7</span>.<span class="hljs-number">798</span>  drugX
<span class="hljs-attribute">4</span>   <span class="hljs-number">61</span>    <span class="hljs-number">0</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">18</span>.<span class="hljs-number">043</span>  drugY
</code></pre><p>Then we have to separate the feature columns(independent variables) from the target column(dependent variable).</p>
<p>The feature columns are the columns that we try to predict from, and the target column is the column with the values we try to predict.</p>
<pre><code><span class="hljs-comment">#independent variables</span>
<span class="hljs-attr">features</span> = [<span class="hljs-string">'Age'</span>, <span class="hljs-string">'Sex'</span>, <span class="hljs-string">'BP'</span>, <span class="hljs-string">'Cholesterol'</span>, <span class="hljs-string">'Na_to_K'</span>]
<span class="hljs-attr">X</span> = df[features]

<span class="hljs-comment">#dependent variable</span>
<span class="hljs-attr">y</span> = df[<span class="hljs-string">'Drug'</span>]
</code></pre><pre><code>     <span class="hljs-string">Age</span>  <span class="hljs-string">Sex</span>  <span class="hljs-string">BP</span>  <span class="hljs-string">Cholesterol</span>  <span class="hljs-string">Na_to_K</span>
<span class="hljs-number">0</span>     <span class="hljs-number">23</span>    <span class="hljs-number">0</span>   <span class="hljs-number">0</span>            <span class="hljs-number">0</span>   <span class="hljs-number">25.355</span>
<span class="hljs-number">1</span>     <span class="hljs-number">47</span>    <span class="hljs-number">1</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">13.093</span>
<span class="hljs-number">2</span>     <span class="hljs-number">47</span>    <span class="hljs-number">1</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">10.114</span>
<span class="hljs-number">3</span>     <span class="hljs-number">28</span>    <span class="hljs-number">0</span>   <span class="hljs-number">2</span>            <span class="hljs-number">0</span>    <span class="hljs-number">7.798</span>
<span class="hljs-number">4</span>     <span class="hljs-number">61</span>    <span class="hljs-number">0</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">18.043</span>
<span class="hljs-string">..</span>   <span class="hljs-string">...</span>  <span class="hljs-string">...</span>  <span class="hljs-string">..</span>          <span class="hljs-string">...</span>      <span class="hljs-string">...</span>
<span class="hljs-number">195</span>   <span class="hljs-number">56</span>    <span class="hljs-number">0</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">11.567</span>
<span class="hljs-number">196</span>   <span class="hljs-number">16</span>    <span class="hljs-number">1</span>   <span class="hljs-number">1</span>            <span class="hljs-number">0</span>   <span class="hljs-number">12.006</span>
<span class="hljs-number">197</span>   <span class="hljs-number">52</span>    <span class="hljs-number">1</span>   <span class="hljs-number">2</span>            <span class="hljs-number">0</span>    <span class="hljs-number">9.894</span>
<span class="hljs-number">198</span>   <span class="hljs-number">23</span>    <span class="hljs-number">1</span>   <span class="hljs-number">2</span>            <span class="hljs-number">2</span>   <span class="hljs-number">14.020</span>
<span class="hljs-number">199</span>   <span class="hljs-number">40</span>    <span class="hljs-number">0</span>   <span class="hljs-number">1</span>            <span class="hljs-number">2</span>   <span class="hljs-number">11.349</span>

[<span class="hljs-number">200</span> <span class="hljs-string">rows</span> <span class="hljs-string">x</span> <span class="hljs-number">5</span> <span class="hljs-string">columns</span>]
<span class="hljs-number">0</span>      <span class="hljs-string">drugY</span>
<span class="hljs-number">1</span>      <span class="hljs-string">drugC</span>
<span class="hljs-number">2</span>      <span class="hljs-string">drugC</span>
<span class="hljs-number">3</span>      <span class="hljs-string">drugX</span>
<span class="hljs-number">4</span>      <span class="hljs-string">drugY</span>
       <span class="hljs-string">...</span>  
<span class="hljs-number">195</span>    <span class="hljs-string">drugC</span>
<span class="hljs-number">196</span>    <span class="hljs-string">drugC</span>
<span class="hljs-number">197</span>    <span class="hljs-string">drugX</span>
<span class="hljs-number">198</span>    <span class="hljs-string">drugX</span>
<span class="hljs-number">199</span>    <span class="hljs-string">drugX</span>
<span class="hljs-attr">Name:</span> <span class="hljs-string">Drug,</span> <span class="hljs-attr">Length:</span> <span class="hljs-number">200</span><span class="hljs-string">,</span> <span class="hljs-attr">dtype:</span> <span class="hljs-string">object</span>
</code></pre><p>Now we can create the actual decision tree, fit it with our details, and save a .png file on the computer:</p>
<pre><code>dtree <span class="hljs-operator">=</span> DecisionTreeClassifier()
dtree <span class="hljs-operator">=</span> dtree.fit(X, y)
data <span class="hljs-operator">=</span> tree.export_graphviz(dtree, out_file<span class="hljs-operator">=</span>None, feature_names<span class="hljs-operator">=</span>features)
graph <span class="hljs-operator">=</span> pydotplus.graph_from_dot_data(data)
graph.write_png(<span class="hljs-string">'mydecisiontree2.png'</span>)

img<span class="hljs-operator">=</span>pltimg.imread(<span class="hljs-string">'mydecisiontree2.png'</span>)
imgplot <span class="hljs-operator">=</span> plt.imshow(img)
plt.show()
</code></pre><h2 id="heading-results-explained">Results Explained</h2>
<p>The decision tree uses your earlier decisions. Let us read the different aspects of the decision tree:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1636529767060/1QVk4HHoK.png" alt="mydecisiontree2.png" /></p>
<h3 id="heading-salt-to-potassium-ratio-natok">Salt to Potassium ratio (Na_to_K)</h3>
<p><strong>Na_to_K &lt;= 14.829</strong> means that every patient with a sodium-potassium of 14.829 or lower will follow the True arrow (to the left), and the rest will follow the False arrow (to the right).</p>
<p><strong>gini = 0.694</strong> refers to the quality of the split, where 0.0 would mean all of the samples got the same result, and 0.5 would mean that the split is done exactly in the middle.</p>
<p><strong>samples = 200</strong> means that there are 200 patients left at this point in the decision, which is all of them since this is the first step.</p>
<p><strong>value = [23, 16, 16, 54, 91]</strong> means that of these 200 patients, 23 will get "drugY", 16 will get "drugB", 16 will get "drugC", 54 will get "drugX" and 91 will get "drugY",</p>
<p>Note, to know these values, we ran:</p>
<pre><code><span class="hljs-selector-tag">print</span>(<span class="hljs-selector-tag">df</span><span class="hljs-selector-attr">[<span class="hljs-string">'Drug'</span>]</span><span class="hljs-selector-class">.value_counts</span>())
</code></pre><pre><code><span class="hljs-string">drugY</span>    <span class="hljs-number">91</span>
<span class="hljs-string">drugX</span>    <span class="hljs-number">54</span>
<span class="hljs-string">drugA</span>    <span class="hljs-number">23</span>
<span class="hljs-string">drugB</span>    <span class="hljs-number">16</span>
<span class="hljs-string">drugC</span>    <span class="hljs-number">16</span>
<span class="hljs-attr">Name:</span> <span class="hljs-string">Drug,</span> <span class="hljs-attr">dtype:</span> <span class="hljs-string">int64</span>
</code></pre><h2 id="heading-predict-values">Predict Values</h2>
<p>We can use the Decision Tree to predict new values.</p>
<p>Example: What prescription(among the five drugs: Y X A B and C) should a 68-year-old female with normal levels of cholesterol and BP and has salt to potassium level of 27.10 take?</p>
<pre><code><span class="hljs-attribute">print</span>(dtree.predict([[<span class="hljs-number">68</span>, <span class="hljs-number">0</span>, <span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">27</span>.<span class="hljs-number">10</span>]]))
<span class="hljs-comment"># ['drugY'] will be the output</span>
</code></pre><p>The system predicts drugY. If you follow the decision tree implemented above, you will arrive at drugY too! Sorry, I cannot explain every aspect of the decision tree, it's quite lengthy and is not within the scope of this tutorial. Let us now proceed to save the model built</p>
<pre><code><span class="hljs-comment"># Save the model</span>
joblib_file = <span class="hljs-string">"DecisionTreeModel.joblib"</span>
joblib.dump(dtree, joblib_file)
</code></pre><p>Now we can start the Django section.</p>
<h2 id="heading-create-an-api-with-django-rest-framework">Create an API With Django Rest Framework</h2>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 <span class="hljs-operator">-</span>m venv myenv
$ source myenv<span class="hljs-operator">/</span>bin<span class="hljs-operator">/</span>activate
(myenv) $ pip install django requests djangorestframework numpy joblib scikit<span class="hljs-operator">-</span>learn
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests djangorestframework numpy joblib scikit-learn
</code></pre><h2 id="heading-setting-up-your-django-application">Setting Up Your Django Application</h2>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp<span class="hljs-operator">/</span>
    manage.py
    mainapp<span class="hljs-operator">/</span>
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp monitor
</code></pre><p>This will create the following:</p>
<pre><code>monitor<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code>INSTALLED_APPS = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'rest_framework'</span>,#<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
    <span class="hljs-string">'monitor'</span>, #<span class="hljs-built_in">new</span> <span class="hljs-type">line</span>
]
</code></pre><p>Ensure you are in the monitor directory then create a new directory called templates and a new file called urls.py. Your directory structure of monitor application should look like this</p>
<pre><code>monitor<span class="hljs-operator">/</span>
    __init__.py
    admin.py
    apps.py
    migrations<span class="hljs-operator">/</span>
    templates<span class="hljs-operator">/</span>
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our monitor app URL to include the URLs we shall create next on the monitor app:</p>
<pre><code><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> <span class="hljs-keyword">admin</span>
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>

urlpatterns = [
    #path(<span class="hljs-string">'admin/'</span>, <span class="hljs-keyword">admin</span>.site.urls),
    path(<span class="hljs-string">''</span>, <span class="hljs-keyword">include</span>(<span class="hljs-string">'monitor.urls'</span>)),#monitor app url
]
</code></pre><p>Now, on the monitor/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-title">path</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> .<span class="hljs-title">views</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-operator">*</span>

<span class="hljs-title">urlpatterns</span> <span class="hljs-operator">=</span> [
    <span class="hljs-title">path</span>(<span class="hljs-string">''</span>, <span class="hljs-title">Prediction</span>.<span class="hljs-title">as_view</span>(), <span class="hljs-title">name</span> <span class="hljs-operator">=</span> <span class="hljs-string">'prediction'</span>),
]
</code></pre><p>Let’s create another directory to store our machine learning model. I’ll also add the dataset to the project for those who want to achieve the whole dataset. (It is not compulsory to create a data folder.)</p>
<pre><code>(venv)$ <span class="hljs-keyword">mkdir</span> ml
(venv)$ <span class="hljs-keyword">mkdir</span> ml/models
(venv)$ <span class="hljs-keyword">mkdir</span> ml/data
</code></pre><p>We also need to tell Django where our machine learning model is located. Add these lines to settings.py file:</p>
<pre><code><span class="hljs-keyword">import</span> os
MODELS = os.path.<span class="hljs-keyword">join</span>(BASE_DIR, <span class="hljs-string">'ml/models'</span>)
</code></pre><h2 id="heading-load-model-through-appspy">Load Model through apps.py</h2>
<p>Load your machine learning models in apps.py so that when the application starts, the trained model is loaded only once. Otherwise, the trained model is loaded each time an endpoint is called, and then the response time will be slower. </p>
<p>Let’s update apps.py</p>
<pre><code><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> joblib
<span class="hljs-keyword">from</span> django.apps <span class="hljs-keyword">import</span> AppConfig
<span class="hljs-keyword">from</span> django.conf <span class="hljs-keyword">import</span> settings


<span class="hljs-keyword">class</span> ApiConfig(AppConfig):
    <span class="hljs-type">name</span> = <span class="hljs-string">'api'</span>
    MODEL_FILE = os.path.<span class="hljs-keyword">join</span>(settings.MODELS, "DecisionTreeModel.joblib")
    model = joblib.<span class="hljs-keyword">load</span>(MODEL_FILE)
</code></pre><h2 id="heading-edit-viewspy">Edit views.py</h2>
<p>The last step is to update views.py. The views will be mainly responsible for two tasks:</p>
<ul>
<li>Process incoming POST requests.</li>
<li>Make a prediction with the incoming data and give the result as a Response.</li>
</ul>
<pre><code><span class="hljs-keyword">import</span> <span class="hljs-title">numpy</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">np</span>
<span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">pandas</span> <span class="hljs-title"><span class="hljs-keyword">as</span></span> <span class="hljs-title">pd</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> .<span class="hljs-title">apps</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-operator">*</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">rest_framework</span>.<span class="hljs-title">views</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">APIView</span>
<span class="hljs-title"><span class="hljs-keyword">from</span></span> <span class="hljs-title">rest_framework</span>.<span class="hljs-title">response</span> <span class="hljs-title"><span class="hljs-keyword">import</span></span> <span class="hljs-title">Response</span>


<span class="hljs-title">class</span> <span class="hljs-title">Prediction</span>(<span class="hljs-title">APIView</span>):
    <span class="hljs-title">def</span> <span class="hljs-title">post</span>(<span class="hljs-title"><span class="hljs-built_in">self</span></span>, <span class="hljs-title">request</span>):
        #<span class="hljs-title">data</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">data</span>
        <span class="hljs-title">age</span><span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'age'</span>)
        <span class="hljs-title">gender</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'gender'</span>)
        <span class="hljs-title">bp</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'bp'</span>)
        <span class="hljs-title">cholesterol</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'cholesterol'</span>)
        <span class="hljs-title">salt</span> <span class="hljs-operator">=</span> <span class="hljs-title">request</span>.<span class="hljs-title">GET</span>.<span class="hljs-title">get</span>(<span class="hljs-string">'salt'</span>)
        <span class="hljs-title">dtree</span> <span class="hljs-operator">=</span> <span class="hljs-title">ApiConfig</span>.<span class="hljs-title">model</span>
        #<span class="hljs-title">predict</span> <span class="hljs-title"><span class="hljs-keyword">using</span></span> <span class="hljs-title">independent</span> <span class="hljs-title">variables</span>
        <span class="hljs-title">PredictionMade</span> <span class="hljs-operator">=</span> <span class="hljs-title">dtree</span>.<span class="hljs-title">predict</span>([[<span class="hljs-title">age</span>, <span class="hljs-title">gender</span>, <span class="hljs-title">cholesterol</span>, <span class="hljs-title">bp</span>, <span class="hljs-title">salt</span>]])
        <span class="hljs-title">response_dict</span> <span class="hljs-operator">=</span> {<span class="hljs-string">"Predicted drug"</span>: <span class="hljs-title">PredictionMade</span>}
        <span class="hljs-title">print</span>(<span class="hljs-title">response_dict</span>)
        <span class="hljs-title"><span class="hljs-keyword">return</span></span> <span class="hljs-title">Response</span>(<span class="hljs-title">response_dict</span>, <span class="hljs-title">status</span><span class="hljs-operator">=</span>200)
</code></pre><h2 id="heading-test-the-api">Test the API</h2>
<p>To test our API, I’ll use <a target="_blank" href="https://docs.python-requests.org/en/latest/">requests</a> library, which is the de facto standard for making HTTP requests in Python. You can also use <a target="_blank" href="https://www.postman.com/">Postman</a> or <a target="_blank" href="https://insomnia.rest/">Insomnia</a> for making the requests.</p>
<p>Let’s predict what drug prescription(among the five drugs: Y X A B and C) should a 68-year-old female with normal levels of cholesterol and BP and has salt to potassium level of 27 take?</p>
<pre><code><span class="hljs-keyword">import</span> requests
predict = [<span class="hljs-built_in">print</span>(x) <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> requests.post(<span class="hljs-string">"http://127.0.0.1:8000/?age=68&amp;gender=0&amp;bp=2&amp;cholesterol=2&amp;salt=27"</span>)]
</code></pre><pre><code>{<span class="hljs-string">'Predicted drug'</span>: [<span class="hljs-string">'drugY'</span>]}
</code></pre><p>Thank you for staying tuned! In case of any questions, feel free to ask in the comment section below.</p>
]]></content:encoded></item><item><title><![CDATA[Introduction: What is Prometheus?]]></title><description><![CDATA[One month ago, I was set out to build an AI system for my home like JARVIS AI from Mark Zuckerberg, inspired by Iron Man. I decided to name it Prometheus, because the myth still makes up the lower strata of my psyche;) The AI system also has a chat b...]]></description><link>https://blog.paulwababu.me.ke/introduction-what-is-prometheus</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/introduction-what-is-prometheus</guid><category><![CDATA[Django]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[APIs]]></category><category><![CDATA[automation]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Sun, 24 Oct 2021 23:19:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635103868810/l4Uip5abB.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>One month ago, I was set out to build an AI system for my home like JARVIS AI from Mark Zuckerberg, inspired by Iron Man. I decided to name it Prometheus, because the myth still makes up the lower strata of my psyche;) The AI system also has a chat bot interface that is connected to the system for remote operations. The system also has some features that are in active development and therefore I cannot blog them for now eg, using a drone for perimeter scouting and controlling home devices like bulbs using Prometheus. Credits to <a target="_blank" href="https://codepen.io/FlyingEmu/full/tclyg">Flying Emu</a> for the Awesome Jarvis UI that I happily copy pasted and reverse engineered a bit to show responses of the user.</p>
<h2 id="heading-what-can-prometheus-do">What can Prometheus Do?</h2>
<p>Our virtual assistant has the following features-:</p>
<p>a.) Web User Interface</p>
<ul>
<li>Support Voice Conversations</li>
<li>Voice controlled SMS reminders</li>
<li>Voice controlled Google Search</li>
<li>Voice controlled web penetration testing and network scanning</li>
<li>Voice controlled intrusion detection via an IP camera with SMS alerts of intruders image(can be 
specified to animals)</li>
<li>Voice controlled <a target="_blank" href="https://developer.safaricom.co.ke/">MPESA</a> business to customer payments(b2c)</li>
<li>Voice controlled MPESA customer to business payments(c2b)</li>
<li>Voice controlled airtime purchase</li>
<li>Symptoms Tracker for medical diagnosis and recommendations.</li>
</ul>
<p>b.) ChatBot User Interface</p>
<ul>
<li>Support Text Conversations</li>
<li>Support automated web penetration testing.</li>
<li>Support domain resolving</li>
<li>Support <a target="_blank" href="https://developer.safaricom.co.ke/">MPESA</a> business to business payments(b2b) by 
simply uploading an image of the till number and the system does a wired transfer automatically.(Depreciated)</li>
<li>Support MPESA customer to business transactions</li>
<li>Get latest news</li>
<li>Panic mode that sends current GPS location shared via whatsapp to primary contacts</li>
</ul>
<p>I am currently in the process of buying smart home devices and a drone to integrate them to Prometheus. One major problem with smart home devices is that they lack common standards to communicate, making integration a challenge.</p>
<h2 id="heading-what-is-prometheus-built-with">What is Prometheus built with?</h2>
<p>Prometheus is basically a hub of API's that leverages a number of artificial intelligence techniques, including speech recognition and object detection. It is written in Python's Django REST Framework, Flask microframework and Javascript.</p>
<h2 id="heading-sneak-peak-feature-voice-enabled-penetration-testing">Sneak Peak Feature: Voice Enabled Penetration Testing</h2>
<iframe width="500" height="315" src="https://www.youtube.com/embed/HBpFMN6b8ng"></iframe>


<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635336079142/c50AZ7bXG.png" alt="Screenshot from 2021-10-27 14-55-59.png" /></p>
<h2 id="heading-see-you-in-the-first-episode-on-how-to-build-prometheus-speech-to-text">See you in the first episode on how to build Prometheus Speech to Text</h2>
]]></content:encoded></item><item><title><![CDATA[Build a web traffic monitor with Django and IPStack]]></title><description><![CDATA[In today's online world, it is important to know where your website traffic comes from in order to help website owners understand their visitors better. In this tutorial, we build a very basic traffic monitor, the traffic monitor will display details...]]></description><link>https://blog.paulwababu.me.ke/build-a-web-traffic-monitor-with-django-and-ipstack</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/build-a-web-traffic-monitor-with-django-and-ipstack</guid><category><![CDATA[Django]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Python]]></category><category><![CDATA[monitoring]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Mon, 04 Oct 2021 19:54:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633365105622/jcalyZWqw.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In today's online world, it is important to know where your website traffic comes from in order to help website owners understand their visitors better. In this tutorial, we build a very basic traffic monitor, the traffic monitor will display details about visitors on the website. For every visitor, there will multiple columns such as time of visit, continent, country and city.</p>
<h2 id="getting-started-with-ipstack-api">Getting started with IPStack API</h2>
<p><a target="_blank" href="ipstack.com">IPStack</a> offers a powerful, real-time IP to geolocation API capable of looking up accurate location data and assessing security threats originating from risky IP addresses. Results are delivered within milliseconds in JSON or XML format. Using the ipstack API you will be able to locate website visitors at first glance and adjust your user experience and application accordingly.</p>
<p>The documentation outlines in detail the API features, available options and integration guides in different programming languages.</p>
<p>Get a <a target="_blank" href="https://ipstack.com/product">free</a> API access key to proceed using this API.</p>
<h2 id="sample-api-response">Sample API Response</h2>
<p>IPStack API responses come with comprehensive location-related data, currency-related data, timezone-related data, connection-related data and security-related data. Have a look at the example below. </p>
<p>Please note: For illustration purposes we have included both Hostname Lookup and the Security Module in the above API response. Please refer to the sections <a target="_blank" href="https://ipstack.com/documentation#hostname">Hostname Lookup </a> and <a target="_blank" href="https://ipstack.com/documentation#security">Security</a> Module for details.</p>
<pre><code>{
  <span class="hljs-attr">"ip"</span>: <span class="hljs-string">"134.201.250.155"</span>,
  <span class="hljs-attr">"hostname"</span>: <span class="hljs-string">"134.201.250.155"</span>,
  <span class="hljs-attr">"type"</span>: <span class="hljs-string">"ipv4"</span>,
  <span class="hljs-attr">"continent_code"</span>: <span class="hljs-string">"NA"</span>,
  <span class="hljs-attr">"continent_name"</span>: <span class="hljs-string">"North America"</span>,
  <span class="hljs-attr">"country_code"</span>: <span class="hljs-string">"US"</span>,
  <span class="hljs-attr">"country_name"</span>: <span class="hljs-string">"United States"</span>,
  <span class="hljs-attr">"region_code"</span>: <span class="hljs-string">"CA"</span>,
  <span class="hljs-attr">"region_name"</span>: <span class="hljs-string">"California"</span>,
  <span class="hljs-attr">"city"</span>: <span class="hljs-string">"Los Angeles"</span>,
  <span class="hljs-attr">"zip"</span>: <span class="hljs-string">"90013"</span>,
  <span class="hljs-attr">"latitude"</span>: <span class="hljs-number">34.0453</span>,
  <span class="hljs-attr">"longitude"</span>: <span class="hljs-number">-118.2413</span>,
  <span class="hljs-attr">"location"</span>: {
    <span class="hljs-attr">"geoname_id"</span>: <span class="hljs-number">5368361</span>,
    <span class="hljs-attr">"capital"</span>: <span class="hljs-string">"Washington D.C."</span>,
    <span class="hljs-attr">"languages"</span>: [
        {
          <span class="hljs-attr">"code"</span>: <span class="hljs-string">"en"</span>,
          <span class="hljs-attr">"name"</span>: <span class="hljs-string">"English"</span>,
          <span class="hljs-attr">"native"</span>: <span class="hljs-string">"English"</span>
        }
    ],
    <span class="hljs-attr">"country_flag"</span>: <span class="hljs-string">"https://assets.ipstack.com/images/assets/flags_svg/us.svg"</span>,
    <span class="hljs-attr">"country_flag_emoji"</span>: <span class="hljs-string">"🇺🇸"</span>,
    <span class="hljs-attr">"country_flag_emoji_unicode"</span>: <span class="hljs-string">"U+1F1FA U+1F1F8"</span>,
    <span class="hljs-attr">"calling_code"</span>: <span class="hljs-string">"1"</span>,
    <span class="hljs-attr">"is_eu"</span>: <span class="hljs-literal">false</span>
  },
  <span class="hljs-attr">"time_zone"</span>: {
    <span class="hljs-attr">"id"</span>: <span class="hljs-string">"America/Los_Angeles"</span>,
    <span class="hljs-attr">"current_time"</span>: <span class="hljs-string">"2018-03-29T07:35:08-07:00"</span>,
    <span class="hljs-attr">"gmt_offset"</span>: <span class="hljs-number">-25200</span>,
    <span class="hljs-attr">"code"</span>: <span class="hljs-string">"PDT"</span>,
    <span class="hljs-attr">"is_daylight_saving"</span>: <span class="hljs-literal">true</span>
  },
  <span class="hljs-attr">"currency"</span>: {
    <span class="hljs-attr">"code"</span>: <span class="hljs-string">"USD"</span>,
    <span class="hljs-attr">"name"</span>: <span class="hljs-string">"US Dollar"</span>,
    <span class="hljs-attr">"plural"</span>: <span class="hljs-string">"US dollars"</span>,
    <span class="hljs-attr">"symbol"</span>: <span class="hljs-string">"$"</span>,
    <span class="hljs-attr">"symbol_native"</span>: <span class="hljs-string">"$"</span>
  },
  <span class="hljs-attr">"connection"</span>: {
    <span class="hljs-attr">"asn"</span>: <span class="hljs-number">25876</span>,
    <span class="hljs-attr">"isp"</span>: <span class="hljs-string">"Los Angeles Department of Water &amp; Power"</span>
  },
  <span class="hljs-attr">"security"</span>: {
    <span class="hljs-attr">"is_proxy"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"proxy_type"</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">"is_crawler"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"crawler_name"</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">"crawler_type"</span>: <span class="hljs-literal">null</span>,
    <span class="hljs-attr">"is_tor"</span>: <span class="hljs-literal">false</span>,
    <span class="hljs-attr">"threat_level"</span>: <span class="hljs-string">"low"</span>,
    <span class="hljs-attr">"threat_types"</span>: <span class="hljs-literal">null</span>
  }
}
</code></pre><h2 id="prerequisites">Prerequisites</h2>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip install django requests
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests
</code></pre><h2 id="setting-up-your-django-application">Setting Up Your Django Application</h2>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp/
    manage.py
    mainapp/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp monitor
</code></pre><p>This will create the following:</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code><span class="hljs-attr">INSTALLED_APPS</span> = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'monitor'</span>, <span class="hljs-comment">#new line</span>
]
</code></pre><p>Ensure you are in the monitor directory then create a new directory called templates and a new file called urls.py. Your directory structure of monitor application should look like this</p>
<pre><code>monitor/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
    templates/
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our monitor app URL to include the URLs we shall create next on the monitor app:</p>
<pre><code><span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> <span class="hljs-keyword">admin</span>
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>

urlpatterns = [
    #path(<span class="hljs-string">'admin/'</span>, <span class="hljs-keyword">admin</span>.site.urls),
    path(<span class="hljs-string">''</span>, <span class="hljs-keyword">include</span>(<span class="hljs-string">'monitor.urls'</span>)),#monitor app url
]
</code></pre><p>Now, on the monitor/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>
<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> views

urlpatterns = [
    path(<span class="hljs-string">''</span>, views.home, <span class="hljs-type">name</span>="home"),
    path(<span class="hljs-string">'monitor/'</span>, views.monitor, <span class="hljs-type">name</span>="monitor"), #<span class="hljs-keyword">system</span> monitor <span class="hljs-keyword">view</span> <span class="hljs-keyword">to</span> be created next
]
</code></pre><p>Create our database models which we shall use to store our website visitors information. On the monitor/models.py file:</p>
<pre><code><span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models

<span class="hljs-comment"># Create your models here.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Monitor</span>(<span class="hljs-params">models.Model</span>):</span>
    continent = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    country = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    city = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    capital = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    datetime = models.DateField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)
    ip = models.CharField(max_length=<span class="hljs-number">50</span>, blank=<span class="hljs-literal">True</span>, null=<span class="hljs-literal">True</span>)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> self.ip
</code></pre><p>Now, on the monitor/views.py file, add the lines below:</p>
<pre><code><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, redirect
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">import</span> psutil
<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime
<span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Monitor
<span class="hljs-keyword">from</span> urllib.parse <span class="hljs-keyword">import</span> urlparse
<span class="hljs-keyword">from</span> django.core.paginator <span class="hljs-keyword">import</span> Paginator

<span class="hljs-comment">#traffic monitor</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">traffic_monitor</span>(<span class="hljs-params">request</span>):</span>
    dataSaved = Monitor.objects.all().order_by(<span class="hljs-string">'-datetime'</span>)
    <span class="hljs-comment"># Getting loadover15 minutes </span>
    load1, load5, load15 = psutil.getloadavg()
    cpu_usage = int((load15/os.cpu_count()) * <span class="hljs-number">100</span>)
    ram_usage = int(psutil.virtual_memory()[<span class="hljs-number">2</span>])
    p = Paginator(dataSaved, <span class="hljs-number">100</span>)
    <span class="hljs-comment">#shows number of items in page</span>
    totalSiteVisits = (p.count)
    <span class="hljs-comment">#find unique page viewers &amp; Duration</span>
    pageNum = request.GET.get(<span class="hljs-string">'page'</span>, <span class="hljs-number">1</span>)
    page1 = p.page(pageNum)
    <span class="hljs-comment">#unique page viewers</span>
    a = Monitor.objects.order_by().values(<span class="hljs-string">'ip'</span>).distinct()
    pp = Paginator(a, <span class="hljs-number">10</span>)
    <span class="hljs-comment">#shows number of items in page</span>
    unique = (pp.count)
    <span class="hljs-comment">#update time</span>
    now = datetime.now()
    data = {
        <span class="hljs-string">"now"</span>:now,
        <span class="hljs-string">"unique"</span>:unique,
        <span class="hljs-string">"totalSiteVisits"</span>:totalSiteVisits,
        <span class="hljs-string">"cpu_usage"</span>: cpu_usage,
        <span class="hljs-string">"ram_usage"</span>: ram_usage,
        <span class="hljs-string">"dataSaved"</span>: page1,
    }
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'traffic_monitor.html'</span>, data)
<span class="hljs-comment">#home page</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">home</span>(<span class="hljs-params">request</span>):</span>
    x_forwarded_for = request.META.get(<span class="hljs-string">'HTTP_X_FORWARDED_FOR'</span>)
    <span class="hljs-keyword">if</span> x_forwarded_for:
        ip = x_forwarded_for.split(<span class="hljs-string">','</span>)[<span class="hljs-number">0</span>]
    <span class="hljs-keyword">else</span>:
        ip = request.META.get(<span class="hljs-string">'REMOTE_ADDR'</span>)
    response = requests.get(<span class="hljs-string">'http://api.ipstack.com/'</span>+ip+<span class="hljs-string">'?access_key=GETYOURACCESSKEY'</span>) <span class="hljs-comment">#change from HTTP to HTTPS on the IPSTACK API if you have a premium account</span>
    rawData = response.json()
    print(rawData) <span class="hljs-comment"># print this out to look at the response</span>
    continent = rawData[<span class="hljs-string">'continent_name'</span>]
    country = rawData[<span class="hljs-string">'country_name'</span>]
    capital = rawData[<span class="hljs-string">'city'</span>]
    city = rawData[<span class="hljs-string">'location'</span>][<span class="hljs-string">'capital'</span>]
    now = datetime.now()
    datetimenow = now.strftime(<span class="hljs-string">"%Y-%m-%d %H:%M:%S"</span>)
    saveNow = Monitor(
        continent=continent,
        country=country,
        capital=capital,
        city=city,
        datetime=datetimenow,
        ip=ip
    )
    saveNow.save()
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'home.html'</span>)
</code></pre><p>In the code above on the home view, the code starts by getting the users IP address. On getting the visitors IP, we then make a request to IPStack with the IP address above appended to the request and store the results to the database. If you wish to collect more information, just add them on the models and add the variable like so above with the respective data you are collecting eg country.</p>
<p>For the traffic monitor view, the code starts buy getting all data on the Monitor table and renders the data on the HTML page which we shall create below. The code also collects the cpu and ram usage of the system. Let us now proceed to rendering the data above on our webpage.</p>
<p>On the monitor/templates folder, create traffic_monitor.html and home.html web page and add the lines below:</p>
<p>monitor/templates/traffic_monitor.html file:</p>
<pre><code><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>ALienx <span class="hljs-symbol">&amp;#8211;</span> Connections<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"canonical"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/examples/album/"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Bootstrap core CSS --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Custom styles for this template --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/examples/album/album.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">header</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"collapse bg-dark"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"navbarHeader"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-8 col-md-7 py-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>About<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-muted"</span>&gt;</span>Add some information about the album below, the author, or any other background context. Make it a few sentences long so folks can pick up some informative tidbits. Then, link them off to some social networking sites or contact information.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-4 offset-md-1 py-4"</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">h4</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>Contact<span class="hljs-tag">&lt;/<span class="hljs-name">h4</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"list-unstyled"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>Follow on Twitter<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>Like on Facebook<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>Email me<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container d-flex justify-content-between"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-brand d-flex align-items-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-desktop"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span> Site Visitors<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-toggler"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"button"</span> <span class="hljs-attr">data-toggle</span>=<span class="hljs-string">"collapse"</span> <span class="hljs-attr">data-target</span>=<span class="hljs-string">"#navbarHeader"</span> <span class="hljs-attr">aria-controls</span>=<span class="hljs-string">"navbarHeader"</span> <span class="hljs-attr">aria-expanded</span>=<span class="hljs-string">"false"</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Toggle navigation"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"navbar-toggler-icon"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"main"</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">section</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron text-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron-heading"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-desktop"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> Site Visitors and Resources Monitor<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead text-muted"</span>&gt;</span>Contact <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>developer<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> if CPU &amp; RAM USAGE exceeds 80%<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>


      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"album py-7 bg-light"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"content-wrapper"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container-fluid"</span>&gt;</span>

                  <span class="hljs-tag">&lt;<span class="hljs-name">ol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"breadcrumb"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"breadcrumb-item"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Dashboard<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"breadcrumb-item active"</span>&gt;</span>Site Traffic &amp; Resources Monitor<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>

                  <span class="hljs-comment">&lt;!-- Icon Cards--&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-3 block"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"circle a"</span>&gt;</span>


                                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>CPU Usage<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>{{ cpu_usage }}%<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-3 block"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"circle b"</span>&gt;</span>

                                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>RAM Usage<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span> 
                                    <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>{{ ram_usage }}%<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span>
                                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-3 block"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"circle c"</span>&gt;</span>


                                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>Total Site Visits<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span> 
                                    <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                                    {{ totalSiteVisits }}
                                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-sm-3 block"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"circle d"</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">b</span>&gt;</span>Unique Page Views<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span>
                                    <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                                    {{ unique }}
                                <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>


                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
                  <span class="hljs-selector-class">.block</span> {
                                    <span class="hljs-attribute">bottom</span>: <span class="hljs-number">30px</span>;
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-attribute">vertical-align</span>: middle;
}
<span class="hljs-selector-class">.circle</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">15px</span>;
    <span class="hljs-attribute">background</span>: white;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">200px</span>;
    <span class="hljs-attribute">color</span>: white;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">170px</span>;
    <span class="hljs-attribute">font-weight</span>: bolder;
    <span class="hljs-attribute">width</span>: <span class="hljs-number">170px</span>;
    <span class="hljs-attribute">display</span>: table;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span> auto;
}
<span class="hljs-selector-class">.circle</span> <span class="hljs-selector-tag">p</span> {
    <span class="hljs-attribute">vertical-align</span>: middle;
    <span class="hljs-attribute">display</span>: table-cell;
}
                    <span class="hljs-selector-class">.a</span> {
                        <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#39c0dc</span>;
                    }
                    <span class="hljs-selector-class">.b</span> {
                        <span class="hljs-attribute">background-color</span>: darkorange;
                    }
                    <span class="hljs-selector-class">.c</span> {
                        <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#5c6dfd</span>;
                    }
                    <span class="hljs-selector-class">.d</span> {
                        <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#f14c6e</span>;
                    }
                    <span class="hljs-selector-class">.g</span> {
                        <span class="hljs-attribute">background-color</span>: greenyellow;
                    }
                    <span class="hljs-selector-class">.f</span>{
                        <span class="hljs-attribute">background-color</span>: fuchsia;
                    }
                </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

                  <span class="hljs-comment">&lt;!-- Example contextTables Card--&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card mb-3"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card-header"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">b</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"color: #0664c9;"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-table"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span> User Sessions<span class="hljs-tag">&lt;/<span class="hljs-name">b</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card-body"</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table-responsive"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">table</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"table table-bordered"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"contextTable"</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"100%"</span> <span class="hljs-attr">cellspacing</span>=<span class="hljs-string">"0"</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">thead</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>IP Address<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Continent<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Country<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>City<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                          <span class="hljs-tag">&lt;/<span class="hljs-name">thead</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">tfoot</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Time<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>IP Address<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Continent<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>Country<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">th</span>&gt;</span>City<span class="hljs-tag">&lt;/<span class="hljs-name">th</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                          <span class="hljs-tag">&lt;/<span class="hljs-name">tfoot</span>&gt;</span>
                          <span class="hljs-tag">&lt;<span class="hljs-name">tbody</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"customer-table"</span>&gt;</span>
                            {% for data in dataSaved.object_list %}
                            <span class="hljs-tag">&lt;<span class="hljs-name">tr</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ data.datetime }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>            
                                <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ data.ip }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ data.continent }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ data.country }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                                <span class="hljs-tag">&lt;<span class="hljs-name">td</span>&gt;</span>{{ data.city }}<span class="hljs-tag">&lt;/<span class="hljs-name">td</span>&gt;</span>
                            <span class="hljs-tag">&lt;/<span class="hljs-name">tr</span>&gt;</span>
                            {% endfor %}
                          <span class="hljs-tag">&lt;/<span class="hljs-name">tbody</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">table</span>&gt;</span>
                      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span>
                      <span class="hljs-tag">&lt;<span class="hljs-name">nav</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"..."</span>&gt;</span>
                        {% if dataSaved.has_other_pages %}
                        <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"pagination justify-content-center"</span>&gt;</span>
                            {% if dataSaved.has_previous %}
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item"</span>&gt;</span>
                            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"?page={{ dataSaved.previous_page_number }}"</span> <span class="hljs-attr">tabindex</span>=<span class="hljs-string">"-1"</span>&gt;</span>Previous<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          {% endif %}

                          {% for i in dataSaved.paginator.page_range %}
                             {% if dataSaved.number == i %}
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item active"</span>&gt;</span>
                              <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>{{ i }}<span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"sr-only"</span>&gt;</span>(current)<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                           <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                          {% endif %}
                          {% endfor %} 
                          <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-item"</span>&gt;</span>
                            {% if dataSaved.has_next %}
                            <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"page-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"?page={{ dataSaved.next_page_number }}"</span>&gt;</span>Next<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
                            {% endif %}
                          <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
                        <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
                        {% endif %}
                    <span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card-footer small text-muted"</span>&gt;</span>Updated at <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"session-update-time"</span>&gt;</span>{{ now }}<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">footer</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-muted"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"float-right"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Back to top<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Need help? <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Contact site developer<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span> or the <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>site admin<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Bootstrap core JavaScript
    ================================================== --&gt;</span>
    <span class="hljs-comment">&lt;!-- Placed at the end of the document so the pages load faster --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://code.jquery.com/jquery-3.2.1.slim.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="xml">window.jQuery || document.write('<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"../../assets/js/vendor/jquery-slim.min.js"</span>&gt;</span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">\</span>/<span class="hljs-attr">script</span>&gt;</span>')</span></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/assets/js/vendor/popper.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/dist/js/bootstrap.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/assets/js/vendor/holder.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>On the monitor/templates/home.html file:</p>
<pre><code><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Required meta tags --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1"</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Bootstrap CSS --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Hello, world!<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello, world!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Optional JavaScript; choose one of the two! --&gt;</span>

    <span class="hljs-comment">&lt;!-- Option 1: Bootstrap Bundle with Popper --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Option 2: Separate Popper and Bootstrap JS --&gt;</span>
    <span class="hljs-comment">&lt;!--
    &lt;script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.9.2/dist/umd/popper.min.js" integrity="sha384-IQsoLXl5PILFhosVNubq5LC7Qb9DXgDA9i+tQ8Zj3iwWAwPtgFTxbJ8NT4GN1R8p" crossorigin="anonymous"&gt;&lt;/script&gt;
    &lt;script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384-cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF" crossorigin="anonymous"&gt;&lt;/script&gt;
    --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><h2 id="testing-if-it-works">Testing if it Works!</h2>
<p>Migrate, then run the server by running the commands below then navigating to the respective port:</p>
<pre><code>(myenv) $ python manage.py makemigrations
(myenv) $ python manage.py migrate
(myenv) $ python manage.py runserver
</code></pre><p>Below is a snapshot of my implementation:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633376622110/HCk3W0TRM.jpeg" alt="save.jpg" /></p>
<h2 id="thanks-for-reading">Thanks for reading!</h2>
<p>I hope you enjoyed this blog as much as i did, incase of any question, feel free to ask on the comment section below.  Note, you can play with this data as you like, like adding a date range filter to show visitors by date or showing the visitors by country. </p>
]]></content:encoded></item><item><title><![CDATA[Deployment Web Security Checklist | Secure your Django App and Apache Server]]></title><description><![CDATA[Hello DEV World!
Ensuring that your website or open web application is secure is critical. Even simple bugs in your code can result in private information being leaked, and people are out there trying to find ways to steal data. In this article, we a...]]></description><link>https://blog.paulwababu.me.ke/deployment-web-security-checklist-or-secure-your-django-app-and-apache-server</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/deployment-web-security-checklist-or-secure-your-django-app-and-apache-server</guid><category><![CDATA[Security]]></category><category><![CDATA[Django]]></category><category><![CDATA[Python]]></category><category><![CDATA[apache]]></category><category><![CDATA[webdev]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Fri, 24 Sep 2021 13:58:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632479783396/4h7xcLMirg.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="hello-dev-world">Hello DEV World!</h3>
<p>Ensuring that your website or open web application is secure is critical. Even simple bugs in your code can result in private information being leaked, and people are out there trying to find ways to steal data. In this article, we are going to check Django and Apache security vulnerabilities and how to fix them.</p>
<h2 id="run-managepy-check-deploy">Run manage.py check --deploy</h2>
<p>Some of the checks we are going to cover can be automated using the command below so lets start by running the command:</p>
<pre><code>python manage.py <span class="hljs-keyword">check</span> <span class="hljs-comment">--deploy</span>
</code></pre><p>You should see some descriptions which provide information about your Django web application vulnerabilities. Note that these may not be the only vulnerabilities in your system. Here are my checklist warnings:</p>
<pre><code>WARNINGS:
?: (security.W004) You have not <span class="hljs-keyword">set</span> a <span class="hljs-keyword">value</span> <span class="hljs-keyword">for</span> the SECURE_HSTS_SECONDS setting. <span class="hljs-keyword">If</span> your entire site <span class="hljs-keyword">is</span> served <span class="hljs-keyword">only</span> <span class="hljs-keyword">over</span> SSL, you may want <span class="hljs-keyword">to</span> <span class="hljs-keyword">consider</span> setting a <span class="hljs-keyword">value</span> <span class="hljs-keyword">and</span> enabling <span class="hljs-keyword">HTTP</span> <span class="hljs-keyword">Strict</span> Transport Security. Be sure <span class="hljs-keyword">to</span> <span class="hljs-keyword">read</span> the documentation <span class="hljs-keyword">first</span>; enabling HSTS carelessly can cause serious, irreversible problems.
?: (security.W008) Your SECURE_SSL_REDIRECT setting is not <span class="hljs-keyword">set</span> <span class="hljs-keyword">to</span> True. Unless your site should be available <span class="hljs-keyword">over</span> <span class="hljs-keyword">both</span> SSL <span class="hljs-keyword">and</span> non-SSL connections, you may want <span class="hljs-keyword">to</span> either <span class="hljs-keyword">set</span> this setting <span class="hljs-literal">True</span> <span class="hljs-keyword">or</span> configure a <span class="hljs-keyword">load</span> balancer <span class="hljs-keyword">or</span> <span class="hljs-keyword">reverse</span>-proxy <span class="hljs-keyword">server</span> <span class="hljs-keyword">to</span> redirect <span class="hljs-keyword">all</span> connections <span class="hljs-keyword">to</span> HTTPS.
?: (security.W009) Your SECRET_KEY has <span class="hljs-keyword">less</span> <span class="hljs-keyword">than</span> <span class="hljs-number">50</span> <span class="hljs-keyword">characters</span>, <span class="hljs-keyword">less</span> <span class="hljs-keyword">than</span> <span class="hljs-number">5</span> <span class="hljs-keyword">unique</span> <span class="hljs-keyword">characters</span>, <span class="hljs-keyword">or</span> it<span class="hljs-string">'s prefixed with '</span>django-insecure-<span class="hljs-string">' indicating that it was generated automatically by Django. Please generate a long and random SECRET_KEY, otherwise many of Django'</span>s <span class="hljs-keyword">security</span>-<span class="hljs-keyword">critical</span> features will be vulnerable <span class="hljs-keyword">to</span> attack.
?: (security.W012) SESSION_COOKIE_SECURE <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">set</span> <span class="hljs-keyword">to</span> True. <span class="hljs-keyword">Using</span> a secure-<span class="hljs-keyword">only</span> <span class="hljs-keyword">session</span> cookie makes it more difficult <span class="hljs-keyword">for</span> network traffic sniffers <span class="hljs-keyword">to</span> hijack <span class="hljs-keyword">user</span> sessions.
?: (security.W016) You have <span class="hljs-string">'django.middleware.csrf.CsrfViewMiddleware'</span> <span class="hljs-keyword">in</span> your MIDDLEWARE, but you have <span class="hljs-keyword">not</span> <span class="hljs-keyword">set</span> CSRF_COOKIE_SECURE <span class="hljs-keyword">to</span> True. <span class="hljs-keyword">Using</span> a secure-<span class="hljs-keyword">only</span> CSRF cookie makes it more difficult <span class="hljs-keyword">for</span> network traffic sniffers <span class="hljs-keyword">to</span> steal the CSRF token.
?: (security.W018) You should <span class="hljs-keyword">not</span> have DEBUG <span class="hljs-keyword">set</span> <span class="hljs-keyword">to</span> <span class="hljs-literal">True</span> <span class="hljs-keyword">in</span> deployment.
?: (security.W020) ALLOWED_HOSTS must <span class="hljs-keyword">not</span> be <span class="hljs-keyword">empty</span> <span class="hljs-keyword">in</span> deployment.
</code></pre><h2 id="indepth-web-scanning-using-mozilla-observatory">Indepth Web Scanning using Mozilla Observatory</h2>
<p>Mozilla Observatory is a tool that is geared towards informing website owners of best practices for securing their sites, covering everything from personal blogs to eCommerce. The tool uses a scoring system to determine how vulnerable or how well implemented security is on your website. The site also includes third-party scanners which test other security aspects of your site.</p>
<p>Here is a sample scan:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632484919207/8YB8DCCz1.png" alt="69djyhdunmbozn7klglr.png" /></p>
<h2 id="checklist-1-http-strict-transport-security">Checklist 1: HTTP Strict Transport Security</h2>
<p>If a website accepts a connection through HTTP and redirects to HTTPS, users may initially communicate with the non-encrypted version of the site before being redirected. This creates an opportunity for a man-in-the-middle attack by allowing a redirect to a malicious site instead of the secure version of the original site.</p>
<p>Add the code below to your settings.py file to inform the browser that it should never load a site using HTTP and should automatically convert all attempts to access the site using HTTP to HTTPS requests instead.</p>
<pre><code><span class="hljs-attr">SECURE_HSTS_SECONDS</span> = <span class="hljs-number">15780000</span>  <span class="hljs-comment"># 6 Months as Recommended</span>
<span class="hljs-attr">SECURE_HSTS_INCLUDE_SUBDOMAINS</span> = <span class="hljs-literal">True</span>
<span class="hljs-attr">SECURE_HSTS_PRELOAD</span> = <span class="hljs-literal">True</span>
</code></pre><h2 id="checklist-2-x-xss-protection">Checklist 2: X-XSS-Protection</h2>
<p>Cross-site scripting (XSS) is a security exploit which allows an attacker to inject into a website malicious client-side code. This code is executed by the victims and lets the attackers bypass access controls and impersonate users.</p>
<p>To block pages from loading when they detect reflected XSS attacks, make sure django.middleware.security.SecurityMiddleware is present in middleware's list and add following lines in your settings.py:</p>
<pre><code><span class="hljs-attr">SECURE_BROWSER_XSS_FILTER</span> = <span class="hljs-literal">True</span>
<span class="hljs-attr">SECURE_CONTENT_TYPE_NOSNIFF</span> = <span class="hljs-literal">True</span>
</code></pre><h2 id="checklist-3-csrf">Checklist 3: CSRF</h2>
<p>CSRF (Cross-Site Request Forgery) is an attack that impersonates a trusted user and sends a website unwanted commands. CSRF attacks typically attempt to change server state, but can also be used to gain access to sensitive data. This can be done, for example, by including malicious parameters in a URL behind a link that purports to go somewhere else. </p>
<p>Once you’ve set up HTTPS, add these lines in your settings.py:</p>
<pre><code><span class="hljs-attr">CSRF_COOKIE_SECURE</span> = <span class="hljs-literal">True</span> <span class="hljs-comment">#to avoid transmitting the CSRF cookie over HTTP accidentally.</span>
<span class="hljs-attr">SESSION_COOKIE_SECURE</span> = <span class="hljs-literal">True</span> <span class="hljs-comment">#to avoid transmitting the session cookie over HTTP accidentally.</span>
</code></pre><h2 id="checklist-4-redirect-http-to-https">Checklist 4: Redirect HTTP to HTTPS</h2>
<p>Once you have SSL installed, you need to redirect visitors to HTTPS site. Add following line to your settings.py to force Django redirect all non-HTTPS requests to HTTPS.</p>
<pre><code><span class="hljs-attr">SECURE_SSL_REDIRECT</span> = <span class="hljs-literal">True</span>
</code></pre><h2 id="checklist-5-content-security-policycsp">Checklist 5: Content Security Policy(CSP)</h2>
<p>Here is where things get interesting. Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate certain types of attacks, including Cross-Site Scripting (XSS) and data injection attacks. These attacks are used for everything from data theft to site defacement to distribute malware. Having third party code creates the need of configuring CSP. This may include inline scripts and styles. </p>
<p>Django has an <a target="_blank" href="https://django-csp-test.readthedocs.io/en/latest/index.html">inbuilt module</a> to implement csp headers. </p>
<p>First, install django-csp via pip or from source:</p>
<pre><code><span class="hljs-attribute">pip</span> install django-csp
</code></pre><p>From source:</p>
<pre><code>git <span class="hljs-keyword">clone</span> https:<span class="hljs-comment">//github.com/mozilla/django-csp.git</span>
cd django-csp
python setup.py install
</code></pre><p>Now edit your project’s settings module, to add the django-csp middleware to MIDDLEWARE, like so:</p>
<pre><code><span class="hljs-attribute">MIDDLEWARE</span> = (
    <span class="hljs-comment"># ...</span>
    <span class="hljs-string">'csp.middleware.CSPMiddleware'</span>,
    <span class="hljs-comment"># ...</span>
)
</code></pre><p>Note: Middleware order does not matter unless you have other middleware modifying the CSP header. That should do it! Lets go on to configuring CSP by adding following lines to your settings.py</p>
<pre><code><span class="hljs-comment"># Content Security Policy</span>
<span class="hljs-attr">CSP_DEFAULT_SRC</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_BASE_URI</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_FRAME_ANCESTORS</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_FORM_ACTION</span> = (<span class="hljs-string">"'self'"</span>, )
<span class="hljs-attr">CSP_STYLE_SRC</span> = (<span class="hljs-string">"'self'"</span>, <span class="hljs-string">'cdnjs.cloudflare.com'</span>,<span class="hljs-string">'fonts.googleapis.com'</span>, <span class="hljs-string">'stackpath.bootstrapcdn.com'</span>, <span class="hljs-string">'getbootstrap.com'</span>)
<span class="hljs-attr">CSP_SCRIPT_SRC</span> = (<span class="hljs-string">"'self'"</span>, <span class="hljs-string">'ajax.googleapis.com'</span>, <span class="hljs-string">'stackpath.bootstrapcdn.com'</span>, <span class="hljs-string">'code.jquery.com'</span>, <span class="hljs-string">'unpkg.com'</span>, <span class="hljs-string">'cdnjs.cloudflare.com'</span>, <span class="hljs-string">'code.jquery.com'</span>, <span class="hljs-string">'getbootstrap.com'</span>)
<span class="hljs-attr">CSP_IMG_SRC</span> = (<span class="hljs-string">"'self'"</span>, <span class="hljs-string">'cdn0.iconfinder.com'</span>, <span class="hljs-string">'media.giphy.com'</span>,<span class="hljs-string">'res.cloudinary.com'</span>)
<span class="hljs-attr">CSP_FONT_SRC</span> = (<span class="hljs-string">"'self'"</span>,<span class="hljs-string">'cdnjs.cloudflare.com'</span>,<span class="hljs-string">'fonts.googleapis.com'</span>, <span class="hljs-string">'fonts.gstatic.com'</span>)
<span class="hljs-attr">CSP_INCLUDE_NONCE_IN</span> = (<span class="hljs-string">"script-src"</span>, <span class="hljs-string">"style-src"</span>)
</code></pre><p>Its really important to clean your code from all these inline styles and scripts. However, some external resources such as the ones included above may be allowed in your CSP policy. Make sure to look at the <a target="_blank" href="https://django-csp-test.readthedocs.io/en/latest/index.html">django-csp</a> documentation in order to know what to update above as the sample above is an example of common tags loaded on the HTML page and also includes inline scripts and style. If you wish to load your scripts from source only then modify the code above to:</p>
<pre><code><span class="hljs-comment"># Content Security Policy</span>
<span class="hljs-attr">CSP_DEFAULT_SRC</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_BASE_URI</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_FRAME_ANCESTORS</span> = (<span class="hljs-string">"'none'"</span>, )
<span class="hljs-attr">CSP_FORM_ACTION</span> = (<span class="hljs-string">"'self'"</span>, )
<span class="hljs-attr">CSP_STYLE_SRC</span> = (<span class="hljs-string">"'self'"</span>, )
<span class="hljs-attr">CSP_SCRIPT_SRC</span> = (<span class="hljs-string">"'self'"</span>, )
<span class="hljs-attr">CSP_IMG_SRC</span> = (<span class="hljs-string">"'self'"</span>, )
<span class="hljs-attr">CSP_FONT_SRC</span> = (<span class="hljs-string">"'self'"</span>, )
</code></pre><h2 id="checklist-6-critical-settings">Checklist 6: Critical settings</h2>
<h3 id="secretkey">SECRET_KEY</h3>
<p>The secret key must be a large random value and it must be kept secret.</p>
<p>Make sure that the key used in production isn’t used anywhere else and avoid committing it to source control. This reduces the number of vectors from which an attacker may acquire the key.</p>
<p>Instead of hardcoding the secret key in your settings module, consider loading it from an environment variable:</p>
<pre><code><span class="hljs-keyword">import</span> os
SECRET_KEY = os.environ[<span class="hljs-string">'SECRET_KEY'</span>]
</code></pre><p>Or from a file:</p>
<pre><code><span class="hljs-keyword">with</span> <span class="hljs-keyword">open</span>(<span class="hljs-string">'/etc/secret_key.txt'</span>) <span class="hljs-keyword">as</span> f:
    SECRET_KEY = f.read().strip()
</code></pre><h3 id="debug">DEBUG</h3>
<p>You must never enable debug in production. Change the following lines in your settings.py file to False to disable it:</p>
<pre><code><span class="hljs-attr">DEBUG</span> = <span class="hljs-literal">False</span>
</code></pre><h2 id="checklist-6-environment-specific-settings">Checklist 6: Environment Specific settings</h2>
<h3 id="allowedhosts">ALLOWED_HOSTS</h3>
<p>When we set DEBUG = False above, Django doesn’t work at all without a suitable value for ALLOWED_HOSTS. This setting is required to protect your site against some CSRF attacks. Change the following line on the settings.py file to point this to your website's domain. </p>
<pre><code><span class="hljs-attr">ALLOWED_HOSTS</span> = [<span class="hljs-string">'alienx.tech'</span>] <span class="hljs-comment">#should point to your domain name</span>
</code></pre><h3 id="databases">DATABASES</h3>
<p>Database connection parameters are probably different in development and in production. Database passwords are very sensitive. You should protect them exactly like we did with SECRET_KEY above. For maximum security, make sure database servers only accept connections from your application servers. </p>
<h2 id="sample-end-result-ranking-by-mozilla-observatory">Sample End Result Ranking by Mozilla Observatory</h2>
<p>Here is my website which implements the features above:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632489105826/w-9f3XCQr.png" alt="alienx.png" /></p>
<p>Please note that this does not mean that our site is proof to hacking by getting an A+, this just means that our site is keeping up with the latest web security standards as per the database of vulnerabilities given by the Mozilla Observatory API. Lets us now proceed to securing our Apache Webserver. Please proceed with the commands below if you are well familiar with apache</p>
<h1 id="how-to-secure-your-apache-server">How to Secure Your Apache Server</h1>
<p>Apache is a popular, open-source web server available for both Linux and Windows systems. It allows configuration for a diverse range of use cases, from HTML webpages to HyperText Preprocessor (PHP) dynamic web application content.Apache provides a secure and robust platform to deploy your web applications. However, it is still important to install the latest security patches and configure the server properly to establish a secure environment for your web applications.</p>
<h2 id="non-privileged-user-account">Non-Privileged User Account</h2>
<p>A non-privileged user is a user that does not belong to the Dynamic Data Masking administration group. The purpose of having one is to restrict the user from unnecessary access to certain tasks within a system. In the context of an Apache web server, this means that it should work in a restricted environment with only the necessary permissions. By default, Apache runs with daemon account privileges. You can create a separate non-root user account to avoid threats in case of security attacks. </p>
<h2 id="keep-apache-updated">Keep Apache Updated</h2>
<p>Apache is famous for providing a secure platform with a highly concerned developer community that rarely faces any security bugs. The good thing about being open source is that for every bad guy out there, there is always around 10 who are good and looking for this bugs to patch. Nevertheless, it is normal to discover issues once the software is released. Hence, it is essential to keep the web server up to date to avail the latest security features. </p>
<p>Run the command below:</p>
<pre><code>sudo apt-<span class="hljs-keyword">get</span> <span class="hljs-keyword">update</span>
sudo apt-<span class="hljs-keyword">get</span> upgrade
</code></pre><h2 id="disable-server-signature">Disable Server Signature</h2>
<p>A server signature is the public identity of your web server and contains sensitive information that could be used to exploit any known vulnerability for example your apache version. The default configuration of an Apache Server exposes a lot of details about the server and its settings. </p>
<p>You can disable these directives by editing the apache2.conf file via vim/nano and add the following directive:</p>
<pre><code>..<span class="hljs-selector-class">.snip</span>...
<span class="hljs-selector-tag">ServerSignature</span> <span class="hljs-selector-tag">Off</span>
..<span class="hljs-selector-class">.snip</span>...
<span class="hljs-selector-tag">ServerTokens</span> <span class="hljs-selector-tag">Prod</span>
..<span class="hljs-selector-class">.snip</span>...
</code></pre><h2 id="disable-server-directory-listings">Disable Server Directory Listings</h2>
<p>The Directory listings displays all content saved in the root folder or sub-directories. The directory files can include sensitive information not intended for public display, such as PHP scripts, configuration files, files containing passwords, logs, etc. This directive can also be added in the .htaaccess of your main website directory
To disallow directory listings, change the Apache server configuration file by editing the apache2.conf file as:</p>
<pre><code>...snip...

&lt;<span class="hljs-built_in">Directory</span> /<span class="hljs-keyword">var</span>/www&gt;

Options -Indexes

&lt;/<span class="hljs-built_in">Directory</span>&gt;

...snip...
</code></pre><h2 id="htaccess-file-settings">.htaccess file Settings</h2>
<p>htaccess files (or "distributed configuration files") provide a way to make configuration changes on a per-directory basis. A file, containing one or more configuration directives, is placed in a particular document directory, and the directives apply to that directory, and all subdirectories thereof. In cases where a user can upload files to the server, this can be exploited by an attacker to upload his or her own “.htaccess” file with malicious configurations. So, if you are not using this feature, you can disable the .htaccess directive by editing the apache.conf file like so:</p>
<pre><code>..<span class="hljs-selector-class">.snip</span>...
<span class="hljs-selector-id">#AccessFileName</span> <span class="hljs-selector-class">.htaccess</span>
..<span class="hljs-selector-class">.snip</span>...
</code></pre><h2 id="prevent-slow-loris-and-dos-attack">Prevent Slow Loris and DoS Attack</h2>
<p>The default installation of an Apache server forces it to wait for requests from clients for too long, which subjects the server to Slow Loris and DoS attacks. The apache2.conf configuration file provides a directive that you can use to lower the timeout value to a few seconds to prevent these types of attacks by editing your apache2.conf file like so:</p>
<pre><code><span class="hljs-attribute">Timeout</span> <span class="hljs-number">60</span>
</code></pre><h2 id="disable-unnecessary-http-requests">Disable Unnecessary HTTP Requests</h2>
<p>Unlimited HTTP/HTTPS requests can also lead to low server performance or a DoS attack. You can limit receiving HTTP requests per-directory by using LimitRequestBody to less than 100K. For instance to create a directive for a folder, add the LimitRequestBody directive below AllowOverride All:</p>
<pre><code>...snip...

&lt;<span class="hljs-built_in">Directory</span> /<span class="hljs-keyword">var</span>/www/your_website&gt;

Options -Indexes

AllowOverride All

LimitRequestBody <span class="hljs-number">995367</span>

&lt;/<span class="hljs-built_in">Directory</span>&gt;

...snip...
</code></pre><h2 id="thanks-for-tuning-in">Thanks for tuning in!</h2>
<p> Thats it for today folks. In the meantime, there are plenty of other ways (not listed above) to secure your Apache web server and Django Web Application, as well. Continue researching and keeping yourself updated about new directives and modules to secure your server further and keep on cross checking your website against the <a target="_blank" href="https://observatory.mozilla.org/">Mozilla observatory scan </a> </p>
]]></content:encoded></item><item><title><![CDATA[Automate Exam Research with Django, Nanonets and Google Search API]]></title><description><![CDATA[Welcome to the first post of my blog. In this article, we shall be building a Django Web Application that allows a user to take a photo of an examination paper, and the application automatically Google's everything for the user and gives back the ans...]]></description><link>https://blog.paulwababu.me.ke/automate-exam-research-with-django-nanonets-and-google-search-api</link><guid isPermaLink="true">https://blog.paulwababu.me.ke/automate-exam-research-with-django-nanonets-and-google-search-api</guid><category><![CDATA[Django]]></category><category><![CDATA[APIs]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[automation]]></category><category><![CDATA[REST API]]></category><dc:creator><![CDATA[Paul Kiragu]]></dc:creator><pubDate>Sun, 19 Sep 2021 17:57:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1632074057214/Pg7LIZ5m5L.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Welcome to the first post of my blog. In this article, we shall be building a Django Web Application that allows a user to take a photo of an examination paper, and the application automatically Google's everything for the user and gives back the answers with their descriptions and links of the sources. Before I start, I would like to say that I did not write this piece of code for the sake of cheating in examination or giving students a platform for cheating, this tool is simply for making examination revision easier and for educational purposes only. Cheating in examinations is illegal and would probably get you expelled!</p>
<p>The full project can be found on my  <a target="_blank" href="https://github.com/paulwababu/examsolver">GitHub repository</a> and the demo <strong>MAY</strong> be found <a target="_blank" href="https://alienx.tech/examsolver">here</a> </p>
<h2 id="prerequisites"><strong>Prerequisites</strong></h2>
<p>We will be using Python3.6+, Django web framework,  <a target="_blank" href="https://nanonets.com/">Nanonets</a>  for character extraction from an image,  <a target="_blank" href="https://cloudinary.com/">Cloudinary</a>  for image storage and  <a target="_blank" href="https://rapidapi.com/apigeek/api/google-search3/">Google Search API</a> for performing the searches. </p>
<p>Following Python best practices, we will create a virtual environment for our project, and install the required packages.</p>
<p>First, create the project directory.</p>
<pre><code>$ mkdir djangoapp
$ cd djangoapp
</code></pre><p>Now, create a virtual environment and install the required packages.</p>
<p>For macOS and Unix systems:</p>
<pre><code>$ python3 -m venv myenv
$ source myenv/bin/activate
(myenv) $ pip install django requests cloudinary
</code></pre><p>For Windows:</p>
<pre><code>$ python3 -m venv myenv
$ myenv\Scripts\activate
(myenv) $ pip install django requests cloudinary
</code></pre><h2 id="configuring-cloudinary"><strong>Configuring Cloudinary </strong></h2>
<p>You will need a Cloudinary account which we shall be using in this project for storing images uploaded by users to be scanned. Cloudinary is an end-to-end image- and video management solution for websites and mobile apps, covering everything from image and video uploads, storage, manipulations, optimizations to delivery.
Once you  <a target="_blank" href="https://cloudinary.com/users/register/free">sign up</a> or login successfully, head over to your Cloudinary console and click on start configuring to get your API key. Note this carefully as we shall be using this shortly</p>
<h2 id="nanonets-for-text-extraction"><strong>Nanonets for text extraction </strong></h2>
<p>Nanonets is a platform that allows for the capture of data from documents instantly at the same time reducing turnaround times and the manual effort required. You can upload your own data and train a model, acquire the JSON responses of each prediction to integrate it with your own systems, and build machine learning-powered apps built on state-of-the-art algorithms and a strong infrastructure. Nanonets also comes with a free tier which allows you to play around with the data on small scale.
Follow the steps below to get started building the model:</p>
<ul>
<li>Get your free API Key</li>
</ul>
<p>Get your free API Key from http://app.nanonets.com/#/keys</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632061068707/pDhPyoNe8.png" alt="nano_api.png" /></p>
<ul>
<li>Upload Images For Training </li>
</ul>
<p>On the <a target="_blank" href="https://app.nanonets.com/">nanonets console</a>, click on new model then create your own, to build your own extractor. Then click upload to add the images to be used for training. You can find them <a target="_blank" href="https://drive.google.com/drive/folders/16re-L3e-zblCW0ZXBRYJZZ3oS5NuszXd?usp=sharing">here</a>. Remember, the more the train data the better the results. The minimum required is 10 files, the recommended is 50 - 100.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632061461999/pdF42UQPN.png" alt="upload.png" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632061742704/fu3JqvZdI.png" alt="up.png" /></p>
<ul>
<li>Once the images have been successfully uploaded, click on next to start managing the model labels. Incase of any errors, the system will not proceed to the manage label section so be sure to ensure you follow the criteria of upload stated. 
Add one label and then click on start training. This label will be what we are extracting from the question paper.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632064071328/ECQX6mN9R.png" alt="start.png" /></p>
<ul>
<li>The model learns from the examples before it can be trained, Mark the data for the label question we created above by simply drawing over the question on the question papers uploaded. Do this on the images till there are at least 10 examples per label. The more the examples, the better the results.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632064841167/mBg5-7fGH.png" alt="tra.png" /></p>
<ul>
<li>Once you are done, start training the model by clicking that button. Once the model training finishes, you will be notified by email and the model state will change on the console to green meaning the model is ready. Depending on the number of images you used, this process will typically take a couple of minutes. </li>
</ul>
<h2 id="setting-up-your-django-application"><strong>Setting Up Your Django Application</strong></h2>
<p>Before we start integrating Django with the model we just trained on nanonets, it is worth stating that we do not need Django to integrate our model, you can use any language/Framework you wish to do the integration. The nanonets console even has some code samples on various language integrations.</p>
<p>First, navigate to the directory djangoapp we created and establish a Django project.</p>
<pre><code>(myenv) $ django-<span class="hljs-keyword">admin</span> startproject mainapp
</code></pre><p>This will auto-generate some files for your project skeleton:</p>
<pre><code>mainapp/
    manage.py
    mainapp/
        __init__.py
        settings.py
        urls.py
        asgi.py
        wsgi.py
</code></pre><p>Now, navigate to the directory you just created (make sure you are in the same directory as manage.py) and create your app directory.</p>
<pre><code>(myenv) $ python manage.py startapp exam
</code></pre><p>This will create the following:</p>
<pre><code>exam/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py
</code></pre><p>On the mainapp/settings.py file, look for the following line and add the app we just created above.</p>
<pre><code><span class="hljs-attr">INSTALLED_APPS</span> = [
    <span class="hljs-string">'django.contrib.admin'</span>,
    <span class="hljs-string">'django.contrib.auth'</span>,
    <span class="hljs-string">'django.contrib.contenttypes'</span>,
    <span class="hljs-string">'django.contrib.sessions'</span>,
    <span class="hljs-string">'django.contrib.messages'</span>,
    <span class="hljs-string">'django.contrib.staticfiles'</span>,
    <span class="hljs-string">'exam'</span>, <span class="hljs-comment">#new line</span>
]
</code></pre><p>Ensure you are in the exam directory then create a new directory called templates and a new file called urls.py. Your directory structure of exam application should look like this</p>
<pre><code>exam/
    __init__.py
    <span class="hljs-keyword">admin</span>.py
    apps.py
    migrations/
    templates/
        __init__.py
    models.py
    tests.py
    urls.py
    views.py
</code></pre><p>Ensure your mainapp/urls.py file, add our exam app URL to include the URLs we shall create next on the exam app:</p>
<pre><code><span class="hljs-string">"""mainapp URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""</span>
<span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
<span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> path, include

urlpatterns = [
    path(<span class="hljs-string">'admin/'</span>, admin.site.urls),
    path(<span class="hljs-string">' '</span>, include(<span class="hljs-string">'exam.urls'</span>)),<span class="hljs-comment">#exam app url</span>
]
</code></pre><p>Now, on the exam/urls.py file, add our website there:</p>
<pre><code><span class="hljs-keyword">from</span> django.urls <span class="hljs-keyword">import</span> <span class="hljs-type">path</span>, <span class="hljs-keyword">include</span>
<span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> views

urlpatterns = [
    path(<span class="hljs-string">' '</span>, views.exams, <span class="hljs-type">name</span>="exams"),#exam researcher <span class="hljs-keyword">view</span> <span class="hljs-keyword">to</span> be created next
]
</code></pre><p>On the mainapp/settings.py file add the configuration key available on the Cloudinary Dashboard:</p>
<pre><code>cloudinary.config( 
  cloud_name = "<span class="hljs-keyword">REPLACE</span> <span class="hljs-keyword">WITH</span> YOUR <span class="hljs-keyword">KEY</span><span class="hljs-string">", 
  api_key = "</span><span class="hljs-keyword">AND</span> REMEMEBER<span class="hljs-string">", 
  api_secret = "</span><span class="hljs-keyword">NEVER</span> EXPOSE <span class="hljs-keyword">KEYS</span> DURING PRODUCTION<span class="hljs-string">" 
)</span>
</code></pre><p>On the exam/views.py, add the following lines of code: Explanation available through comments</p>
<pre><code><span class="hljs-keyword">from</span> django.shortcuts <span class="hljs-keyword">import</span> render, redirect
<span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">import</span> cloudinary.uploader
<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed
<span class="hljs-keyword">from</span> <span class="hljs-type">time</span> <span class="hljs-keyword">import</span> <span class="hljs-type">time</span>

<span class="hljs-meta">#exams researcher</span>
def exams(request):
    <span class="hljs-keyword">if</span> request.<span class="hljs-keyword">method</span> == <span class="hljs-string">'POST'</span>:
        files = request.FILES[<span class="hljs-string">'files'</span>]
        upload_data = cloudinary.uploader.upload(files)
        imageData = upload_data[<span class="hljs-string">'secure_url'</span>]
        nanoNetsApi = <span class="hljs-string">'https://app.nanonets.com/api/v2/OCR/Model/418edf37-dsdadfgs/LabelUrls/'</span> #replace THE MODEL ID <span class="hljs-number">418</span>edf37-dsdadfgs <span class="hljs-keyword">WITH</span> YOURS <span class="hljs-built_in">found</span> <span class="hljs-keyword">on</span> the nanonets model console https://app.nanonets.com/#/models
        headers = {<span class="hljs-string">'accept'</span>: <span class="hljs-string">'application/x-www-form-urlencoded'</span>}
        data = {<span class="hljs-string">'urls'</span> : [imageData]}
        response = requests.request(<span class="hljs-string">'POST'</span>, nanoNetsApi, headers=headers, auth=requests.auth.HTTPBasicAuth(<span class="hljs-string">'REPLACE'</span>, <span class="hljs-string">''</span>), data=data)
        test = response.json()
        <span class="hljs-keyword">for</span> quiz <span class="hljs-keyword">in</span> test[<span class="hljs-string">'result'</span>]:
            predicted = quiz[<span class="hljs-string">'prediction'</span>]
            q1 = predicted[<span class="hljs-number">0</span>][<span class="hljs-string">'ocr_text'</span>]
            q2 = predicted[<span class="hljs-number">1</span>][<span class="hljs-string">'ocr_text'</span>]
            q3 = predicted[<span class="hljs-number">2</span>][<span class="hljs-string">'ocr_text'</span>]
            q4 = predicted[<span class="hljs-number">3</span>][<span class="hljs-string">'ocr_text'</span>]
            q5 = predicted[<span class="hljs-number">4</span>][<span class="hljs-string">'ocr_text'</span>]
            q6 = predicted[<span class="hljs-number">5</span>][<span class="hljs-string">'ocr_text'</span>]
            q7 = predicted[<span class="hljs-number">6</span>][<span class="hljs-string">'ocr_text'</span>]
            q8 = predicted[<span class="hljs-number">7</span>][<span class="hljs-string">'ocr_text'</span>]
            q9 = predicted[<span class="hljs-number">8</span>][<span class="hljs-string">'ocr_text'</span>]
            q10 = predicted[<span class="hljs-number">9</span>][<span class="hljs-string">'ocr_text'</span>]
            q11 = predicted[<span class="hljs-number">10</span>][<span class="hljs-string">'ocr_text'</span>]
            q12 = predicted[<span class="hljs-number">11</span>][<span class="hljs-string">'ocr_text'</span>]
            q13 = predicted[<span class="hljs-number">12</span>][<span class="hljs-string">'ocr_text'</span>]
            q14 = predicted[<span class="hljs-number">13</span>][<span class="hljs-string">'ocr_text'</span>]

        q1Format = q1.replace(" ", "+")
        q2Format = q2.replace(" ", "+")
        q3Format = q3.replace(" ", "+")
        q4Format = q4.replace(" ", "+")
        q5Format = q5.replace(" ", "+")
        q6Format = q6.replace(" ", "+")
        q7Format = q7.replace(" ", "+")
        q8Format = q8.replace(" ", "+")
        q9Format = q9.replace(" ", "+")
        q10Format = q10.replace(" ", "+")
        q11Format = q11.replace(" ", "+")
        q12Format = q12.replace(" ", "+")
        q13Format = q13.replace(" ", "+")
        q14Format = q14.replace(" ", "+")

        q1SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q1Format
        q2SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q2Format
        q3SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q3Format
        q4SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q4Format
        q5SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q5Format
        q6SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q6Format
        q7SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q7Format
        q8SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q8Format
        q9SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q9Format
        q10SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q10Format
        q11SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q11Format
        q12SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q12Format
        q13SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q13Format
        q14SearchUrl = "https://google-search3.p.rapidapi.com/api/v1/search/q="+q14Format

        searchHeader = { <span class="hljs-string">'x-user-agent'</span>: "desktop", <span class="hljs-string">'x-rapidapi-host'</span>: "google-search3.p.rapidapi.com", <span class="hljs-string">'x-rapidapi-key'</span>: "43628cd680msh1812b1660500eb7p182976jsn5dda2f77f08f" }

        searchResponseQ1 = requests.request("GET", q1SearchUrl, headers=searchHeader)
        searchResponseQ2 = requests.request("GET", q2SearchUrl, headers=searchHeader)
        searchResponseQ3 = requests.request("GET", q3SearchUrl, headers=searchHeader)
        searchResponseQ4 = requests.request("GET", q4SearchUrl, headers=searchHeader)
        searchResponseQ5 = requests.request("GET", q5SearchUrl, headers=searchHeader)
        searchResponseQ6 = requests.request("GET", q6SearchUrl, headers=searchHeader)
        searchResponseQ7 = requests.request("GET", q7SearchUrl, headers=searchHeader)
        searchResponseQ8 = requests.request("GET", q8SearchUrl, headers=searchHeader)
        searchResponseQ9 = requests.request("GET", q9SearchUrl, headers=searchHeader)
        searchResponseQ10 = requests.request("GET", q10SearchUrl, headers=searchHeader)
        searchResponseQ11 = requests.request("GET", q11SearchUrl, headers=searchHeader)
        searchResponseQ12 = requests.request("GET", q12SearchUrl, headers=searchHeader)
        searchResponseQ13 = requests.request("GET", q13SearchUrl, headers=searchHeader)
        searchResponseQ14 = requests.request("GET", q14SearchUrl, headers=searchHeader)

        q1resp = searchResponseQ1.json()
        q1res = q1resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q2resp = searchResponseQ1.json()
        q2res = q2resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q4resp = searchResponseQ4.json()
        q4res = q4resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q5resp = searchResponseQ5.json()
        q5res = q5resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q6resp = searchResponseQ6.json()
        q6res = q6resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q7resp = searchResponseQ7.json()
        q7res = q7resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q8resp = searchResponseQ8.json()
        q8res = q8resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q9resp = searchResponseQ9.json()
        q9res = q9resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q10resp = searchResponseQ10.json()
        q10res = q10resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q11resp = searchResponseQ11.json()
        q11res = q11resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q12resp = searchResponseQ12.json()
        q12res = q12resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q13resp = searchResponseQ13.json()
        q13res = q13resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        q14resp = searchResponseQ14.json()
        q14res = q14resp.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        tester = searchResponseQ3.json()
        testa = tester.<span class="hljs-keyword">get</span>(<span class="hljs-string">'results'</span>)

        context = {
            "tester":testa,
            "q1res":q1res,
            "q2res":q2res,
            "q4res":q4res,
            "q5res":q5res,
            "q6res":q6res,
            "q7res":q7res,
            "q8res":q8res,
            "q9res":q9res,
            "q10res":q10res,
            "q11res":q11res,
            "q12res":q12res,
            "q13res":q13res,
            "q14res":q14res,
        }
        <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'exam_results.html'</span>, context)
    <span class="hljs-keyword">return</span> render(request, <span class="hljs-string">'exams.html'</span>)
</code></pre><p>This view function starts by accepting POST data from the exam.html file that we shall create below. The file uploaded by the user is then uploaded to Cloudinary. If successful, the URL of the image generated by cloudinary is then taken and run against nanonets model we created. </p>
<p>Next, on the mainapp/exam/templates directory, create a exams.html and exam_results.html files and paste the code below to render our output</p>
<p>mainapp/exam/templates/exams.html</p>
<pre><code><span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Favicons --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>AlienX - Exam Researcher<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Bootstrap core CSS --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
      <span class="hljs-selector-id">#upload</span>{<span class="hljs-attribute">opacity</span>:<span class="hljs-number">0</span>}<span class="hljs-selector-id">#upload-label</span>{<span class="hljs-attribute">position</span>:absolute;<span class="hljs-attribute">top</span>:<span class="hljs-number">50%</span>;<span class="hljs-attribute">left</span>:<span class="hljs-number">1rem</span>;<span class="hljs-attribute">transform</span>:<span class="hljs-built_in">translateY</span>(-<span class="hljs-number">50%</span>)}<span class="hljs-selector-class">.image-area</span>{<span class="hljs-attribute">border</span>:<span class="hljs-number">2px</span> dashed <span class="hljs-built_in">rgba</span>(<span class="hljs-number">255</span>,<span class="hljs-number">255</span>,<span class="hljs-number">255</span>,.<span class="hljs-number">7</span>);<span class="hljs-attribute">padding</span>:<span class="hljs-number">1rem</span>;<span class="hljs-attribute">position</span>:relative}<span class="hljs-selector-class">.image-area</span><span class="hljs-selector-pseudo">::before</span>{<span class="hljs-attribute">content</span>:<span class="hljs-string">'Uploaded image result'</span>;<span class="hljs-attribute">color</span>:<span class="hljs-number">#fff</span>;<span class="hljs-attribute">font-weight</span>:<span class="hljs-number">700</span>;<span class="hljs-attribute">text-transform</span>:uppercase;<span class="hljs-attribute">position</span>:absolute;<span class="hljs-attribute">top</span>:<span class="hljs-number">50%</span>;<span class="hljs-attribute">left</span>:<span class="hljs-number">50%</span>;<span class="hljs-attribute">transform</span>:<span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>,-<span class="hljs-number">50%</span>);<span class="hljs-attribute">font-size</span>:.<span class="hljs-number">8rem</span>;<span class="hljs-attribute">z-index</span>:<span class="hljs-number">1</span>}<span class="hljs-selector-class">.image-area</span> <span class="hljs-selector-tag">img</span>{<span class="hljs-attribute">z-index</span>:<span class="hljs-number">2</span>;<span class="hljs-attribute">position</span>:relative}<span class="hljs-selector-tag">body</span>{<span class="hljs-attribute">min-height</span>:<span class="hljs-number">100vh</span>;<span class="hljs-attribute">background-color</span>:<span class="hljs-number">#757f9a</span>;<span class="hljs-attribute">background-image</span>:<span class="hljs-built_in">linear-gradient</span>(<span class="hljs-number">147deg</span>,#<span class="hljs-number">757</span>f9a <span class="hljs-number">0</span>,#d7dde8 <span class="hljs-number">100%</span>)}
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://code.jquery.com/jquery-3.3.1.slim.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.bundle.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-comment">/*  ==========================================
    SHOW UPLOADED IMAGE
* ========================================== */</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">readURL</span>(<span class="hljs-params">input</span>) </span>{
    <span class="hljs-keyword">if</span> (input.files &amp;&amp; input.files[<span class="hljs-number">0</span>]) {
        <span class="hljs-keyword">var</span> reader = <span class="hljs-keyword">new</span> FileReader();

        reader.onload = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">e</span>) </span>{
            $(<span class="hljs-string">'#imageResult'</span>)
                .attr(<span class="hljs-string">'src'</span>, e.target.result);
        };
        reader.readAsDataURL(input.files[<span class="hljs-number">0</span>]);
    }
}

$(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
    $(<span class="hljs-string">'#upload'</span>).on(<span class="hljs-string">'change'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
        readURL(input);
    });
});

<span class="hljs-comment">/*  ==========================================
    SHOW UPLOADED IMAGE NAME
* ========================================== */</span>
<span class="hljs-keyword">var</span> input = <span class="hljs-built_in">document</span>.getElementById( <span class="hljs-string">'upload'</span> );
<span class="hljs-keyword">var</span> infoArea = <span class="hljs-built_in">document</span>.getElementById( <span class="hljs-string">'upload-label'</span> );

input.addEventListener( <span class="hljs-string">'change'</span>, showFileName );
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">showFileName</span>(<span class="hljs-params"> event </span>) </span>{
  <span class="hljs-keyword">var</span> input = event.srcElement;
  <span class="hljs-keyword">var</span> fileName = input.files[<span class="hljs-number">0</span>].name;
  infoArea.textContent = <span class="hljs-string">'File name: '</span> + fileName;
}
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container py-5"</span>&gt;</span>

        <span class="hljs-comment">&lt;!-- For demo purpose --&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white text-center"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"display-4"</span>&gt;</span>Question Researcher<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead mb-0"</span>&gt;</span>Take Image or Upload existing image<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-5 font-weight-light"</span>&gt;</span>Powered by
                <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://alienx.tech"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-white"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">u</span>&gt;</span>alienXconnections<span class="hljs-tag">&lt;/<span class="hljs-name">u</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://res.cloudinary.com/mhmd/image/upload/v1564991372/image_pxlho1.svg"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"150"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"mb-4"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span>


        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row py-4"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-lg-6 mx-auto"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">method</span> = <span class="hljs-string">"post"</span> <span class="hljs-attr">enctype</span>=<span class="hljs-string">"multipart/form-data"</span>&gt;</span>
                    {% csrf_token %}
                <span class="hljs-comment">&lt;!-- Upload image input--&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"input-group mb-3 px-2 py-2 rounded-pill bg-white shadow-sm"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"upload"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"file"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"files"</span> <span class="hljs-attr">onchange</span>=<span class="hljs-string">"readURL(this);"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control border-0"</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"upload-label"</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"upload"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-weight-light text-muted"</span>&gt;</span>Choose file<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"input-group-append"</span>&gt;</span>
                        <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"upload"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-light m-0 rounded-pill px-4"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fa fa-cloud-upload mr-2 text-muted"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">small</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-uppercase font-weight-bold text-muted"</span>&gt;</span>Choose file<span class="hljs-tag">&lt;/<span class="hljs-name">small</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
                    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

                <span class="hljs-comment">&lt;!-- Uploaded image area--&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"font-italic text-white text-center"</span>&gt;</span>The image uploaded will be rendered inside the box below.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"image-area mt-4"</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"imageResult"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"#"</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"img-fluid rounded shadow-sm mx-auto d-block"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary btn-block"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span>&gt;</span>Next<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>mainapp/exam/templates/exam_results.html</p>
<pre><code>
<span class="hljs-meta">&lt;!doctype <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1, shrink-to-fit=no"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"author"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">""</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/assets/img/favicons/favicon.ico"</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Top navbar example for Bootstrap<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>


    <span class="hljs-comment">&lt;!-- Bootstrap core CSS --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/dist/css/bootstrap.min.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Custom styles for this template --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/examples/navbar-static/navbar-top.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>



    <span class="hljs-tag">&lt;<span class="hljs-name">main</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"main"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Researched Questions with their links<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

        {% for aa in q1res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{aa.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{aa.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{aa.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for bb in q2res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{bb.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{bb.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{bb.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for tt in tester %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{tt.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{tt.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{tt.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for ee in q4res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{ee.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{ee.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ee.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for ff in q5res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{ff.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{ff.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ff.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for gg in q6res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{gg.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{gg.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{gg.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for hh in q7res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{hh.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{hh.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{hh.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for ii in q8res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{ii.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{ii.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{ii.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}

      {% for jj in q9res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{jj.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{jj.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{jj.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}


      {% for kk in q10res %}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"jumbotron"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{{kk.title}}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"lead"</span>&gt;</span>{{kk.description}}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-lg btn-primary"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"{{kk.link}}"</span> <span class="hljs-attr">role</span>=<span class="hljs-string">"button"</span>&gt;</span>Site<span class="hljs-symbol">&amp;raquo;</span><span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {% endfor %}




    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>

    <span class="hljs-comment">&lt;!-- Bootstrap core JavaScript
    ================================================== --&gt;</span>
    <span class="hljs-comment">&lt;!-- Placed at the end of the document so the pages load faster --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://code.jquery.com/jquery-3.2.1.slim.min.js"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="xml">window.jQuery || document.write('<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/assets/js/vendor/jquery-slim.min.js"</span>&gt;</span><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">\</span>/<span class="hljs-attr">script</span>&gt;</span>')</span></span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/assets/js/vendor/popper.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://getbootstrap.com/docs/4.0/dist/js/bootstrap.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre><p>One major problem with the system, it takes around 40 seconds to run all those requests, this is where concurrency comes in. Try running the files below which simulate the request above and tell the difference! The code was able to run from 40 seconds to 4 seconds just by adding a few lines of code</p>
<p>without_concurrency.py</p>
<pre><code><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed
<span class="hljs-keyword">from</span> time <span class="hljs-keyword">import</span> time

q1Format = <span class="hljs-string">"elon+musk"</span>
q2Format = <span class="hljs-string">"elon+musk+age"</span>
q3Format = <span class="hljs-string">"elon+musk+networth"</span>
q4Format = <span class="hljs-string">"elon+musk+wife"</span>
q5Format = <span class="hljs-string">"elon+musk+h"</span>
q6Format = <span class="hljs-string">"elon+musk+faces"</span>
q7Format = <span class="hljs-string">"elon+musk+kenya"</span>
q8Format = <span class="hljs-string">"elon+musk+uhuru+kenyatta"</span>
q9Format = <span class="hljs-string">"elon+musk+m"</span>
q10Format = <span class="hljs-string">"elon+musk+de"</span>
q11Format = <span class="hljs-string">"elon+musk+y"</span>
q12Format = <span class="hljs-string">"elon+musk+mate"</span>
q13Format = <span class="hljs-string">"elon+musk+uk"</span>
q14Format = <span class="hljs-string">"elon+musk+london"</span>

url_list = [
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q1Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q2Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q3Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q4Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q5Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q6Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q7Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q8Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q9Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q10Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q11Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q12Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q13Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q14Format,
]

searchHeader = { <span class="hljs-string">'x-user-agent'</span>: <span class="hljs-string">"desktop"</span>, <span class="hljs-string">'x-rapidapi-host'</span>: <span class="hljs-string">"google-search3.p.rapidapi.com"</span>, <span class="hljs-string">'x-rapidapi-key'</span>: <span class="hljs-string">"43628cd680msh1812b1660500eb7p182976jsn5dda2f77f08f"</span> }


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_file</span>(<span class="hljs-params">url</span>):</span>
    html = requests.get(url, headers=searchHeader, stream=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> html.status_code

start = time()

<span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> url_list:
    print(download_file(url))

print(<span class="hljs-string">f'Time taken: <span class="hljs-subst">{time() - start}</span>'</span>)
</code></pre><p>with_concurrency.py</p>
<pre><code><span class="hljs-keyword">import</span> requests
<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed
<span class="hljs-keyword">from</span> time <span class="hljs-keyword">import</span> time

q1Format = <span class="hljs-string">"elon+musk"</span>
q2Format = <span class="hljs-string">"elon+musk+age"</span>
q3Format = <span class="hljs-string">"elon+musk+networth"</span>
q4Format = <span class="hljs-string">"elon+musk+wife"</span>
q5Format = <span class="hljs-string">"elon+musk+salary"</span>
q6Format = <span class="hljs-string">"elon+musk+faces"</span>
q7Format = <span class="hljs-string">"elon+musk+kenya"</span>
q8Format = <span class="hljs-string">"elon+musk+uhuru+kenyatta"</span>
q9Format = <span class="hljs-string">"elon+musk+trump"</span>
q10Format = <span class="hljs-string">"elon+musk+spacex"</span>
q11Format = <span class="hljs-string">"elon+musk+cats"</span>
q12Format = <span class="hljs-string">"elon+musk+mate"</span>
q13Format = <span class="hljs-string">"elon+musk+uk"</span>
q14Format = <span class="hljs-string">"elon+musk+london"</span>

url_list = [
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q1Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q2Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q3Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q4Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q5Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q6Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q7Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q8Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q9Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q10Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q11Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q12Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q13Format,
    <span class="hljs-string">"https://google-search3.p.rapidapi.com/api/v1/search/q="</span>+q14Format,
]


searchHeader = { <span class="hljs-string">'x-user-agent'</span>: <span class="hljs-string">"desktop"</span>, <span class="hljs-string">'x-rapidapi-host'</span>: <span class="hljs-string">"google-search3.p.rapidapi.com"</span>, <span class="hljs-string">'x-rapidapi-key'</span>: <span class="hljs-string">"43628cd680msh1812b1660500eb7p182976jsn5dda2f77f08f"</span> }


<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">download_file</span>(<span class="hljs-params">url</span>):</span>
    <span class="hljs-keyword">global</span> html
    html = requests.get(url, headers=searchHeader, stream=<span class="hljs-literal">True</span>)
    <span class="hljs-keyword">return</span> html.status_code

start = time()

processes = []
<span class="hljs-keyword">with</span> ThreadPoolExecutor(max_workers=<span class="hljs-number">20</span>) <span class="hljs-keyword">as</span> executor:
    <span class="hljs-keyword">for</span> url <span class="hljs-keyword">in</span> url_list:
        processes.append(executor.submit(download_file, url))

<span class="hljs-keyword">for</span> task <span class="hljs-keyword">in</span> as_completed(processes):
    print(task.result())


print(<span class="hljs-string">f'Time taken: <span class="hljs-subst">{time() - start}</span>'</span>)
</code></pre><h2 id="testing-it-works">Testing It Works</h2>
<p>Make sure you are in the directory with manage.py, and run</p>
<pre><code>(myenv) $ python manage.py runserver
</code></pre><p>You should see the port that your Django application is running on. But this is still running from your computer. Check out the snapshots below on the final product</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632074395622/DhIfXx0Zs.jpeg" alt="Screenshot_20210919-201053_Gallery.jpg" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632074415882/4uFK8dXTK.jpeg" alt="Screenshot_20210919-201058_Gallery (1).jpg" /></p>
<h2 id="thanks-for-reading">Thanks for Reading!</h2>
<p>This is my first blog so I know might have left out a lot of details especially on the views part, incase of any question, let me know in the comment section. </p>
]]></content:encoded></item></channel></rss>