<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jonathan Okah, Author at Be on the Right Side of Change</title>
	<atom:link href="https://blog.finxter.com/author/jonathanokah23424/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.finxter.com/author/jonathanokah23424/</link>
	<description></description>
	<lastBuildDate>Thu, 31 Aug 2023 14:04:19 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.finxter.com/wp-content/uploads/2020/08/cropped-cropped-finxter_nobackground-32x32.png</url>
	<title>Jonathan Okah, Author at Be on the Right Side of Change</title>
	<link>https://blog.finxter.com/author/jonathanokah23424/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>How I Created Charts Using Charts.js in Django Web Application</title>
		<link>https://blog.finxter.com/how-i-created-charts-using-charts-js-in-django-web-application/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Fri, 04 Aug 2023 14:37:00 +0000</pubDate>
				<category><![CDATA[Data Visualization]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1547017</guid>

					<description><![CDATA[<p>If you want to display charts in your Django web application, whether it is a bar chart, a pie chart, or other charts, you have so many options at your disposal &#8212; from using Plotly in Python language to using HighCharts.js or Charts.js in JavaScript. The beauty of using the later over the former is ... <a title="How I Created Charts Using Charts.js in Django Web Application" class="read-more" href="https://blog.finxter.com/how-i-created-charts-using-charts-js-in-django-web-application/" aria-label="Read more about How I Created Charts Using Charts.js in Django Web Application">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-charts-using-charts-js-in-django-web-application/">How I Created Charts Using Charts.js in Django Web Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>If you want to display charts in your Django web application, whether it is a bar chart, a pie chart, or other charts, you have so many options at your disposal &#8212; from using <a href="https://blog.finxter.com/plotly-dash-vs-streamlit/" data-type="post" data-id="997098" target="_blank" rel="noreferrer noopener">Plotly</a> in Python language to using <code>HighCharts.js</code> or <code>Charts.js</code> in JavaScript.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img fetchpriority="high" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-33.png" alt="" class="wp-image-1547022" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-33.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-33-300x169.png 300w" sizes="(max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>The beauty of using the later over the former is that all the heavy lifting has been done for us. By placing the link in your template, you can take advantage of all the available features. We <a rel="noreferrer noopener" href="https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/" data-type="post" data-id="1529193" target="_blank">have already demonstrated</a> how to display charts using <code>Highcharts.js</code> in a Django web application.</p>



<p>In this tutorial, we will pay attention to <code>Charts.js</code>. Specifically, we will learn:</p>



<ol class="wp-block-list" type="1">
<li>Another way to populate the database other than the ones mentioned while learning how to do so with <code>Highcharts.js</code></li>



<li>How to query the database to display the data structured in such a way that <code>Charts.js</code> can understand.</li>



<li>How to display both bar chart and pie chart</li>
</ol>



<h2 class="wp-block-heading">The Model</h2>



<p>For this project, we will use the data from Kaggle<sup>1</sup> that shows the richest people in the world as of 2022. The data contains several columns but we are only interested in just a few of them. Let us create a database model for the dataset.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.db import models

GENDER = (
    ('M', 'Male'),
    ('F', 'Female'),
)

class Richest(models.Model):
    name = models.CharField(max_length=100)
    gender = models.CharField(max_length=1, choices=GENDER)
    net_worth = models.IntegerField()
    country = models.CharField(max_length=100)
    source = models.CharField(max_length=100)

    def __str__(self):
        return self.name
</pre>



<p>The model contains names of the richest people in the world, their net worth, country of origin and their source of wealth.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-34.png" alt="" class="wp-image-1547023" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-34.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-34-300x169.png 300w" sizes="(max-width: 720px) 100vw, 720px" /></figure>
</div>


<h2 class="wp-block-heading">Populating the database</h2>



<p>In the previous tutorial project on creating a chart using <code>Highcharts.js</code>, I showed you one of the ways to populate a database. I wrote a script from the Django shell to populate the database. In this tutorial, we will learn a different method.</p>



<p>We will use Django’s <code>BaseCommand</code> class to create a custom management command that populates the database using the dataset.</p>



<p>Start by creating new folders inside the app folder. For example, assuming the name of your Django app is charts and is created in your current directory, run the following in your Ubuntu terminal:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">mkdir charts/management/commands -p</pre>



<p>The <code>p</code> flag makes it possible to create a nested folder in one command. Inside the <code>commands</code> folder, create a new file named <code>populate_db.py</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">nano charts/management/commands/populate_db.py</pre>



<p>let’s first import the required modules:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.core.management.base import BaseCommand
from charts.models import Richest
import csv
import math
</pre>



<p><code>BaseCommand</code>&nbsp;is a class provided by Django that serves as the base class for writing custom management commands. Management commands are scripts that can be run from the command line to perform various tasks related to your Django app.</p>



<p>The&nbsp;<code>BaseCommand</code>&nbsp;class provides several useful methods and attributes that make it easy to write custom management commands. When you create a custom management command by subclassing&nbsp;<code>BaseCommand</code>, you need to override the&nbsp;<code>handle</code>&nbsp;method to define the behavior of your command.</p>



<p>The&nbsp;<code>handle</code>&nbsp;method is called when the command is executed, and it receives any command-line arguments passed to the command as keyword arguments.</p>



<p>In addition to the&nbsp;<code>handle</code>&nbsp;method, the&nbsp;<code>BaseCommand</code>&nbsp;class provides several other methods and attributes that you can use when writing custom management commands.</p>



<p>For example, as we shall see, you can use the&nbsp;<code>add_arguments</code>&nbsp;method to define custom command-line arguments for your command, and you can use the&nbsp;<code>stdout</code>&nbsp;and&nbsp;<code>stderr</code>&nbsp;attributes to write output to the Ubuntu terminal.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Command(BaseCommand):
    help = 'Populate the database using a CSV file'

    def add_arguments(self, parser):
        parser.add_argument('forbes_2022_billionaires.csv', type=str, help='The path to the CSV file')

    def handle(self, *args, **options):
        csv_file = options['forbes_2022_billionaires.csv']

        with open(csv_file, 'r') as f:
            reader = csv.DictReader(f)
            for row in reader:
                skip_row = False
                for value in row.values():
                    try:
                        if math.isnan(float(value)):
                            skip_row = True
                            break
                    except ValueError:
                        pass
                if skip_row:
                    continue
                net_worth = int(float(row['finalWorth']))
                obj, created = Richest.objects.get_or_create(
                    name=row['personName'],
                    gender=row['gender'],
                    net_worth=net_worth,
                    country=row['countryOfCitizenship'],
                    source=row['source']
                 )

        self.stdout.write(self.style.SUCCESS('Successfully populated the database'))
</pre>



<p>We define a new&nbsp;<code>Command</code>&nbsp;class that inherits from&nbsp;<code>BaseCommand</code>.</p>



<p>In the <code>add_arguments</code> method, we define a new command-line argument called <code>csv_file</code> that specifies the path to the CSV file. In the <code>handle</code> method, we <a href="https://blog.finxter.com/read-a-csv-file-to-a-pandas-dataframe/" data-type="post" data-id="440655" target="_blank" rel="noreferrer noopener">read the data from the CSV file</a> and use a conditional statement to check if any of the values in the current row are NaN.</p>



<p>If any value is NaN, we use the&nbsp;<code>continue</code>&nbsp;statement to skip this row and move on to the next one. Otherwise, we use the&nbsp;<code>get_or_create</code>&nbsp;method to add the data to the database. Finally, we use the&nbsp;<code>self.stdout.write</code>&nbsp;method to print a success message.</p>



<p>We use a <a rel="noreferrer noopener" href="https://blog.finxter.com/how-to-write-a-nested-for-loop-in-one-line-python/" data-type="post" data-id="11859" target="_blank">nested loop</a> to iterate over each value in the row. For each value, we use a try-except block to try to convert the value to a float and check if it is NaN. If a <code>ValueError</code> exception occurs, we catch it and ignore it using <a href="https://blog.finxter.com/python-pass-statement/" data-type="post" data-id="29709" target="_blank" rel="noreferrer noopener">the <code>pass</code> statement</a>.</p>



<p>If any value in the row is NaN, we set the&nbsp;<code>skip_row</code>&nbsp;variable to&nbsp;<code>True</code>&nbsp;and use the&nbsp;<code>break</code>&nbsp;statement to exit the inner loop. After the inner loop completes, we use an if statement to check if the&nbsp;<code>skip_row</code>&nbsp;variable is&nbsp;<code>True</code>. If it is, we use the&nbsp;<code>continue</code>&nbsp;statement to skip this row and move on to the next one.</p>



<p>However, a problem arises from the dataset. The <code>net_worth</code> field is an <code>IntegerField</code>. Whereas, the data type of the <code>finalWorth</code> column is float. To avoid errors, we first convert the value of the <code>net_worth</code> field in the current row to a float using the <code>float</code> function, and then convert it to an integer using the <code>int</code> function. We then assign this integer value to the <code>net_worth</code> field of the <code>Richest</code> model instance using the <code>get_or_create</code> method.</p>



<p>Make sure you have the <code>forbes_2022_billionaires.csv</code> file downloaded and placed in your current directory. Then, run the command we defined from the command line using the <code>manage.py</code> script like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">python3 manage.py populate_db forbes_2022_billionaires.csv</pre>



<p>Afterward, a success message will be displayed. We have populated our database. Open the admin interface to see it.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-35.png" alt="" class="wp-image-1547026" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-35.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-35-300x169.png 300w" sizes="(max-width: 720px) 100vw, 720px" /></figure>
</div>


<h2 class="wp-block-heading">Displaying charts using Charts.js</h2>



<p>Make sure you have included the <code>Charts.js</code> library in your template by adding the following script tag to the <code>&lt;head></code> section of your HTML file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;script src="https://cdn.jsdelivr.net/npm/chart.js">&lt;/script></pre>



<p>Next, add a <code>&lt;canvas></code> element to your template where you want to display the chart. Give this element an id so you can reference it in your JavaScript code.</p>



<p>Here’s an example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;canvas id="myChart">&lt;/canvas></pre>



<p>In this demonstration, we will query the database to:</p>



<ol class="wp-block-list" type="1">
<li>Calculate total net worth of each country</li>



<li>Get the top 10 richest people in the world</li>



<li>Get the top 10 richest women in the world</li>



<li>Get the distribution of wealth by gender</li>
</ol>



<p>We will also include a pie chart. You can always check the source code for more details.</p>



<h2 class="wp-block-heading">Displaying the total net worth of each country</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.shortcuts import render
from django.db.models import Sum
from .models import Richest

def TotalNetWorth(request):
    # Query the database to get the data
    data = Richest.objects.values('country').annotate(total_net_worth=Sum('net_worth')).order_by('-total_net_worth')

    # Prepare the data for the chart
    chart_data = []
    for item in data:
        chart_data.append({
            'country': item['country'],
            'total_net_worth': item['total_net_worth']
        })

    # Render the template with the chart data
    return render(request, 'total_net_worth.html', {'chart_data': chart_data})
</pre>



<p>We group the data by country using the <code>values</code> method, and using the <code><a href="https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/" data-type="post" data-id="1529193" target="_blank" rel="noreferrer noopener">annotate</a></code> method, we calculate the total net worth of each country. </p>



<p>Next, we prepare the data for the chart by creating a new list called <code>chart_data</code> and appending a dictionary for each item in the query result. </p>



<p>Each <a href="https://blog.finxter.com/python-dictionary/" data-type="post" data-id="5232" target="_blank" rel="noreferrer noopener">dictionary</a> contains two keys: <code>'country'</code> and <code>'total_net_worth'</code>, which represent the country and its total net worth, respectively.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;script>
    var ctx = document.getElementById('myChart').getContext('2d');
    var chart = new Chart(ctx, {
        type: 'bar',
        data: {
            labels: {{ chart_data|safe }}.map(item => item.country),
            datasets: [{
                label: 'Total Net Worth',
                data: {{ chart_data|safe }}.map(item => item.total_net_worth),
                backgroundColor: 'rgba(54, 162, 235, 0.2)',
                borderColor: 'rgba(54, 162, 235, 1)',
                borderWidth: 1	
            }]
        },
        options: {
            scales: {
                y: {
                    beginAtZero: true
                }
            }
        }
    });
&lt;/script>
</pre>



<p>Here, we create a new <code>Chart</code> object and pass it the context of the <code>&lt;canvas></code> element and an options object that specifies the type of chart and its data. </p>



<p>We use the <code>chart_data</code> variable passed as context to populate the chart with data. </p>



<p>Then, we use the <code>map</code> method to extract the country names and total net worth values from the <code>chart_data</code> and assign them to the <code>labels</code> and <code>data</code> properties of the chart’s datasets.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-36.png" alt="" class="wp-image-1547027" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-36.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-36-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>Check out the source code for a demonstration of a pie chart. It’s almost the same.</p>



<h2 class="wp-block-heading">Displaying the top ten richest people in the world</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def TopTenRichest(request):
    # Query the database to get the data
    data = Richest.objects.order_by('-net_worth')[:10]

    # Prepare the data for the chart
    chart_data = []
    for item in data:
        chart_data.append({
            'name': item.name,
            'net_worth': item.net_worth
        })

    # Render the template with the chart data
    return render(request, 'top_ten_richest.html', {'chart_data': chart_data})
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-37.png" alt="" class="wp-image-1547028" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-37.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-37-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>The following code shows how to display a pie chart using <code>Charts.js</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
    type: 'pie',
    data: {
        labels: {{ chart_data|safe }}.map(item => item.name),
        datasets: [{
            label: 'Net Worth',
            data: {{ chart_data|safe }}.map(item => item.net_worth),
            backgroundColor: [
                'rgb(255, 99, 132)',
                'rgb(54, 162, 235)',
                'rgb(255, 205, 86)',
                'rgb(75, 192, 192)',
                'rgb(153, 102, 255)',
                'rgb(255, 159, 64)',
                'rgb(255, 99, 132)',
                'rgb(54, 162, 235)',
                'rgb(255, 205, 86)',
                'rgb(75, 192, 192)'
            ],
            hoverOffset: 4
        }]
    },
    options: {
        title: {
            display: true,
            text: 'Top Ten Richest People'
        }
    }
});
</pre>



<p>This code creates a new <code>Chart</code> object and sets its type to <code>'pie'</code>. The data for the chart is taken from the <code>chart_data</code> variable that was passed to the template from <code>TopTenRichest</code> view function. </p>



<p>The <code>labels</code> for the chart are set to the names of the richest people, and the data for the chart is set to their net worths.</p>



<p>The source code also contains the bar chart example.</p>



<h2 class="wp-block-heading">Displaying the top ten richest women</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def TopRichestWomen(request):
    data = Richest.objects.filter(gender='F').order_by('-net_worth')[:10]
    names = [item.name for item in data]
    net_worths = [item.net_worth for item in data]
    return render(request, 'top_richest_women.html', {
        'names': names,
        'net_worths': net_worths
    })
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-38.png" alt="" class="wp-image-1547031" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-38.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-38-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<h2 class="wp-block-heading">Distribution of wealth by gender</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def WealthByGender(request):
    # Query the database to get the total net worth for each gender
    male_net_worth = Richest.objects.filter(gender='M').aggregate(Sum('net_worth'))['net_worth__sum']
    female_net_worth = Richest.objects.filter(gender='F').aggregate(Sum('net_worth'))['net_worth__sum']

    # Prepare the data for the chart
    data = {
        'labels': ['Male', 'Female'],
        'datasets': [{
            'data': [male_net_worth, female_net_worth],
            'backgroundColor': ['#36A2EB', '#FF6384']
        }]
    }

    # Render the chart using the Chart.js library
    return render(request, 'wealth_by_gender.html', {'data': data})
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-39.png" alt="" class="wp-image-1547034" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-39.png 720w, https://blog.finxter.com/wp-content/uploads/2023/08/image-39-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>And this is the pie chart. Check the source code for more details:</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>In this project tutorial, we have learned various ways to query our database, structure the data and displayed them using <code>charts.js</code>, a JavaScript library for data visualization. We saw how Django interacts with <code>charts.js</code> to display charts on a template.</p>



<p>We also learned another way to populate the database by using Django’s <code>BaseCommand</code> class. Due to the nature of the dataset, we were restricted to only bar and pie charts. However, we can apply the process to create other charts.</p>



<p>Use the knowledge you learned to integrate charts in your Django web application.</p>



<ul class="wp-block-list">
<li><a rel="noreferrer noopener" href="https://www.kaggle.com/datasets/prasertk/forbes-worlds-billionaires-list-2022?resource=download" target="_blank">Forbes World&#8217;s Billionaires List 2022 | Kaggle</a></li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter size-large"><a href="https://blog.finxter.com/the-math-of-becoming-a-millionaire/" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="1024" height="618" src="https://blog.finxter.com/wp-content/uploads/2023/08/image-40-1024x618.png" alt="" class="wp-image-1547035" srcset="https://blog.finxter.com/wp-content/uploads/2023/08/image-40-1024x618.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/08/image-40-300x181.png 300w, https://blog.finxter.com/wp-content/uploads/2023/08/image-40-768x463.png 768w, https://blog.finxter.com/wp-content/uploads/2023/08/image-40.png 1363w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a></figure>
</div>


<p class="has-base-background-color has-background"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Recommended</strong>: <a href="https://blog.finxter.com/the-math-of-becoming-a-millionaire/" data-type="URL" data-id="https://blog.finxter.com/the-math-of-becoming-a-millionaire/" target="_blank" rel="noreferrer noopener">The Math of Becoming a Millionaire in 13 Years</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-charts-using-charts-js-in-django-web-application/">How I Created Charts Using Charts.js in Django Web Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Created an Audiobook App with Streamlit</title>
		<link>https://blog.finxter.com/how-i-created-an-audiobook-app-with-streamlit/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 27 Jul 2023 19:19:52 +0000</pubDate>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Streamlit]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1529295</guid>

					<description><![CDATA[<p>Welcome to another project tutorial using the Streamlit Library. It’s been a while since I created projects using this framework. The previous project tutorial was on creating a weather app which was the third series on developing a single application using three Python frameworks. In this tutorial, we will learn to design something really interesting, ... <a title="How I Created an Audiobook App with Streamlit" class="read-more" href="https://blog.finxter.com/how-i-created-an-audiobook-app-with-streamlit/" aria-label="Read more about How I Created an Audiobook App with Streamlit">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-an-audiobook-app-with-streamlit/">How I Created an Audiobook App with Streamlit</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Welcome to another project tutorial using the Streamlit Library. It’s been a while since I created projects using this framework. The previous project tutorial was on <a rel="noreferrer noopener" href="https://blog.finxter.com/how-i-built-a-weather-app-with-python-streamlit/" data-type="post" data-id="1413206" target="_blank">creating a weather app</a> which was the third series on developing a single application using three Python frameworks.</p>



<p>In this tutorial, we will learn to design something really interesting, that is, an audio app.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="708" height="398" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-400.png" alt="" class="wp-image-1529296" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-400.png 708w, https://blog.finxter.com/wp-content/uploads/2023/07/image-400-300x169.png 300w" sizes="auto, (max-width: 708px) 100vw, 708px" /></figure>
</div>


<p>Many of us do enjoy reading books especially novels and motivational books. However, due to your busy schedule, you may find it difficult to set aside time, relax on a sofa, and read that interesting book you have or you borrowed from a friend.</p>



<p>All hope is not lost. You can still read even at the go through an audiobook. Many find it enjoyable listening to audiobooks while going about their normal activities for the day.</p>



<p>As Python developers, this will be a nice project to create and add to our portfolio. That is exactly what we are going to do in this project tutorial.</p>



<p>We will create a Streamlit application where users can upload a book in PDF format and have it converted to an audiobook. The user can then decide to listen to the audio while attending to other tasks or download it to listen to later.</p>



<p class="has-base-2-background-color has-background"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a rel="noreferrer noopener" href="https://jonaben1-audiobook-app-app-mo8nd5.streamlit.app/" data-type="URL" data-id="https://jonaben1-audiobook-app-app-mo8nd5.streamlit.app/" target="_blank">Try it yourself in this interactive Streamlit app I created for you</a></p>



<h2 class="wp-block-heading">Creating the Application</h2>



<p>I assume you have already created a virtual environment for this project. Let’s get started. The code will span just a few lines. So, it will be easy to understand. Moreover, I will explain everything step by step.</p>



<h3 class="wp-block-heading">Step 1: Import the required modules</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import streamlit as st
from gtts import gTTS
import pdfplumber
import docx
import ebooklib
from ebooklib import epub
</pre>



<p><code>Streamlit</code>&nbsp;is used to create the Streamlit application,&nbsp;<code>gTTS</code>&nbsp;(Google’s Text-to-Speech) is used to convert text to speech,&nbsp;<code>pdfplumber</code>&nbsp;is used to extract text from PDF files,&nbsp;<code>docx</code>&nbsp;is used to extract text from DOCX files, and&nbsp;<code>ebooklib</code>&nbsp;and&nbsp;<code>epub</code>&nbsp;are used to extract text from EPUB files.</p>



<h3 class="wp-block-heading">Step 2: Create a file uploader widget</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">st.title("Streamlit AudioBook App")
st.info('Convert your E-book to audiobook')
book = st.file_uploader('Please upload your file', type=['pdf', 'txt', 'docx', 'epub'])
</pre>



<p>After setting the title and subtitle of the Streamlit application, we create a file uploader widget that allows the user to upload a file. The&nbsp;<code>type</code>&nbsp;parameter specifies the allowed file types, which in this case are PDF, TXT, DOCX, and EPUB. This gives you the option to upload other file extensions other than PDF.</p>



<h3 class="wp-block-heading">Step 3: Create a function to handle file extraction based on the extension</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def extract_text_from_docx(file):
    doc = docx.Document(file)
    full_text = []
    for para in doc.paragraphs:
        full_text.append(para.text)
    return '\n'.join(full_text)

def extract_text_from_epub(file):
    book = epub.read_epub(file)
    chapters = []
    for item in book.get_items():
        if item.get_type() == ebooklib.ITEM_DOCUMENT:
            chapters.append(item.get_content())
    return '\n'.join(chapters)
</pre>



<p>We define two functions, <code>extract_text_from_docx</code> and <code>extract_text_from_epub</code>, which are used to extract text from DOCX and EPUB files, respectively. </p>



<p>The <code>extract_text_from_docx</code> function uses the <code>docx</code> library to read the contents of a DOCX file and extract the text from its paragraphs. </p>



<p>The <code>extract_text_from_epub</code> function uses the <code>ebooklib</code> and <code>epub</code> libraries to read the contents of an EPUB file and extract the text from its chapters.</p>



<p>An EPUB file is made up of multiple items, each of which can have a different type. Some common item types include&nbsp;<code>ITEM_DOCUMENT</code>, which represents the main content of the book,&nbsp;<code>ITEM_IMAGE</code>, which represents images, and&nbsp;<code>ITEM_STYLE</code>, which represents style sheets.</p>



<p>The condition is used to check if the current item being processed is a document item. If it is, the content of the item is extracted and appended to the <code>chapters</code> list. This ensures that only the main content of the book is included in the final text, and other items such as images and style sheets are ignored.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="708" height="398" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-401.png" alt="" class="wp-image-1529297" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-401.png 708w, https://blog.finxter.com/wp-content/uploads/2023/07/image-401-300x169.png 300w" sizes="auto, (max-width: 708px) 100vw, 708px" /></figure>
</div>


<h3 class="wp-block-heading">Step 4: Check if the file has been uploaded and extract it</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">if book:
    if book.type == 'application/pdf':
        all_text = ""
        with pdfplumber.open(book) as pdf:
            for text in pdf.pages:
                single_page_text = text.extract_text()
                all_text = all_text + '\n' + str(single_page_text)
</pre>



<p>Once the book is uploaded, it checks the type. If the uploaded file is a PDF file, it then uses the <code>pdfplumber</code> library to open the PDF file and extract its text. </p>



<p>The text from each page of the PDF is concatenated into a single string, separated by newline characters.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">elif book.type == 'text/plain':
        all_text = book.read().decode("utf-8")
elif book.type == 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
        all_text = extract_text_from_docx(book)
elif book.type == 'application/epub+zip':
        all_text = extract_text_from_epub(book)
</pre>



<p>If the uploaded file is a TXT file, it reads its contents directly and decodes them as UTF-8 text. If the uploaded file is a DOCX file, the code calls the <code>extract_text_from_docx</code> function to extract its text. Whereas, if the uploaded file is an EPUB, it calls the <code>exract_text_from_epub</code> function to extract the text.</p>



<p>MIME types are used to identify the format of a file or data, and are commonly used in email attachments, HTTP headers, and other contexts where it’s important to specify the type of data being transmitted. <code>application/vnd.openxmlformats-officedocument.wordprocessingml.document</code>&nbsp;is a MIME type that represents a Microsoft Word document in the Office Open XML (OOXML) format.&nbsp;</p>



<h3 class="wp-block-heading">Step 5: Convert the extracted text to speech</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">tts = gTTS(all_text)
tts.save('audiobook.mp3')
</pre>



<p>Using the&nbsp;<code>gTTS</code>&nbsp;library, we convert the extracted text into speech. The&nbsp;<code>gTTS</code>&nbsp;function takes the text as input and returns a&nbsp;<code>gTTS</code>&nbsp;object. The&nbsp;<code>save</code>&nbsp;method of this object is then called to save the generated speech as an MP3 file named&nbsp;<code>audiobook.mp3</code>.</p>



<p>Once the code is run, you should see an <code>audiobook.mp3</code> file in your project folder.</p>



<h3 class="wp-block-heading">Step 6: Open and read the content of the file</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">audio_file = open('audiobook.mp3', 'rb')
audio_bytes = audio_file.read()
</pre>



<p>The&nbsp;<code>audiobook.mp3</code>&nbsp;file is opened in binary mode and its contents are read into a variable named&nbsp;<code>audio_bytes</code>. This variable contains the binary data of the MP3 file.</p>



<h3 class="wp-block-heading">Step 7: Create an audio player widget</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">st.audio(audio_bytes, format='audio/wav', start_time=0)</pre>



<p>We use Streamlit’s <code>audio</code> function to create an audio player widget that allows the user to play back the generated speech. The <code>audio_bytes</code> variable is passed as the first argument to specify the audio data to be played. </p>



<p>The <code>format</code> parameter is set to <code>'audio/wav'</code> to specify the format of the audio data, and the start_time parameter is set to 0 to start playback from the beginning of the audio.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="708" height="398" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-402.png" alt="" class="wp-image-1529303" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-402.png 708w, https://blog.finxter.com/wp-content/uploads/2023/07/image-402-300x169.png 300w" sizes="auto, (max-width: 708px) 100vw, 708px" /></figure>
</div>


<h2 class="wp-block-heading">Conclusion</h2>



<p>Congratulations! You just created an audiobook app in just seven steps. Check the full code on <a href="https://github.com/Jonaben1/audiobook_app" data-type="URL" data-id="https://github.com/Jonaben1/audiobook_app" target="_blank" rel="noreferrer noopener">GitHub</a>. The three dots at the audio widget give you the option to download the audio file if you want to listen later. Please note that the conversion may take some time depending on your internet network and the size of the file.</p>



<p>Now, all you need to do is to <a href="https://jonaben1-audiobook-app-app-mo8nd5.streamlit.app/" data-type="URL" data-id="https://jonaben1-audiobook-app-app-mo8nd5.streamlit.app/" target="_blank" rel="noreferrer noopener">deploy the app on Streamlit Cloud</a>. Then, upload your favorite book and enjoy listening on the go.</p>
<p>The post <a href="https://blog.finxter.com/how-i-created-an-audiobook-app-with-streamlit/">How I Created an Audiobook App with Streamlit</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Added User Authentication to My Hacker News Clone Django Website</title>
		<link>https://blog.finxter.com/how-i-added-user-authentication-to-my-hacker-news-clone-django-website/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 27 Jul 2023 19:10:52 +0000</pubDate>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1529281</guid>

					<description><![CDATA[<p>In this tutorial, we will continue designing the Hacker News clone website by adding a user authentication feature. Anyone interested in using our application to share the latest news must be authenticated. This means the person has to register on the platform and be able to log in and log out. Once authenticated, the creator ... <a title="How I Added User Authentication to My Hacker News Clone Django Website" class="read-more" href="https://blog.finxter.com/how-i-added-user-authentication-to-my-hacker-news-clone-django-website/" aria-label="Read more about How I Added User Authentication to My Hacker News Clone Django Website">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-added-user-authentication-to-my-hacker-news-clone-django-website/">How I Added User Authentication to My Hacker News Clone Django Website</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>In this tutorial, we will continue designing the <a href="https://blog.finxter.com/how-i-coded-the-hacker-news-clone-in-django-web-application/" data-type="post" data-id="1460992" target="_blank" rel="noreferrer noopener">Hacker News clone website</a> by adding a user authentication feature. Anyone interested in using our application to share the latest news must be authenticated. This means the person has to register on the platform and be able to log in and log out.</p>



<p>Once authenticated, the creator can be able to submit or edit posts. I have already demonstrated how to authenticate users in previous <a href="https://blog.finxter.com/how-i-added-a-user-authentication-to-my-django-real-estate-application/" data-type="post" data-id="1479871" target="_blank" rel="noreferrer noopener">Django project tutorials</a>. Since we are replicating an existing application, we have to show how the particular feature was designed.</p>



<p>Therefore, in this series, we will:</p>



<ol class="wp-block-list" type="1">
<li>Create a user authentication feature for registering, sign-in and sign-out functionalities.</li>



<li>Add more views to allow authenticated users to submit or edit posts.</li>



<li>Give readers the option to show their appreciation for the news read by upvoting or downvoting the post.</li>
</ol>



<h2 class="wp-block-heading">User Authentication</h2>



<h3 class="wp-block-heading">Signup View</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login

def signup(request):
    if request.user.is_authenticated:
        return redirect('/')

    if request.method == 'POST':
        form = UserCreationForm(request.POST)

        if form.is_valid():
            form.save()
            username = form.cleaned_data['username']
            password = form.cleaned_data['password1']
            user = authenticate(username=username, password=password)
            login(request, user)
            return redirect('/')

        else:
            return render(request,'signup.html',{'form':form})
    else:
        form = UserCreationForm()
        return render(request, 'signup.html', {'form':form})
</pre>



<p>This code is a Django view function that handles user registration. It imports the <code>UserCreationForm</code> from Django&#8217;s built-in authentication forms, as well as the authenticate, login, and logout functions from Django&#8217;s authentication system.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-396.png" alt="" class="wp-image-1529283" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-396.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-396-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>The signup function first checks if the user is already authenticated. If they are, it redirects them to the homepage. If the user is not authenticated, the function checks if the request method is POST, meaning that the form has been submitted.</p>



<p>If the form has been submitted, it creates a new instance of the <code>UserCreationForm</code> with the data from the request. It then checks if the form is valid. If it is, it saves the new user, authenticates them using their username and password, logs them in, and redirects them to the homepage.</p>



<p>If the form is not valid, it returns a response that renders a template called <code>signup.html</code> and passes in the invalid form to be displayed to the user.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-397.png" alt="" class="wp-image-1529284" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-397.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-397-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>If the request method is not POST, meaning that the form has not been submitted, it creates a new instance of the <code>UserCreationForm</code> and returns a response that renders the <code>signup.html</code> template and passes in the empty form to be displayed to the user.</p>



<h3 class="wp-block-heading">Sign-in View</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import  login

def signin(request):
    if request.user.is_authenticated:
        return redirect('/')

    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username =username, password = password)

        if user is not None:
            login(request,user)
            return redirect('/')
        else:
            form = AuthenticationForm()
            return render(request,'signin.html',{'form':form})
    else:
        form = AuthenticationForm()
        return render(request, 'signin.html', {'form':form})
</pre>



<p>This code checks if the user is already authenticated, and if they are, it redirects them to the homepage.</p>



<p>If the user is not authenticated, the function checks if the request method is POST, which means the form has been submitted. If it has, it retrieves the username and password from the request data and uses the authenticate function to check if the provided credentials are valid.</p>



<p>If the credentials are valid, it logs in the user using the login function and redirects them to the homepage. If the credentials are not valid, it creates a new instance of Django&#8217;s built-in <code>AuthenticationForm</code> and returns a response that renders a template called <code>signin.html</code> and passes in the form to be displayed to the user.</p>



<p>If the request method is not POST, that means the form has not been submitted, it creates a new instance of the <code>AuthenticationForm</code> and returns a response that renders the <code>signin.html</code> template and passes in the empty form to be displayed to the user.</p>



<h3 class="wp-block-heading">Logout View</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.contrib.auth import logout
        
def signout(request):
    logout(request)
    return redirect('/')
</pre>



<p>This view function uses the&nbsp;<code>logout</code>&nbsp;function from Django’s authentication system to log out the user associated with the given request. After logging out the user, it redirects them to the homepage.</p>



<p>And here are the <code>urlpatterns</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('signin', signin, name='signin'),
path('signup', signup, name='signup'),
path('signout', signout, name='signout'),
</pre>



<h2 class="wp-block-heading">Adding More Views</h2>



<h3 class="wp-block-heading">Submit View</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from .forms import PostForm

def SubmitPostView(request):
    if request.user.is_authenticated:
        form = PostForm()

        if request.method == "POST":
            form = PostForm(request.POST)

            if form.is_valid():
                title = form.cleaned_data['title']
                url = form.cleaned_data['url']
                description = form.cleaned_data['description']
                creator = request.user
                created_on = datetime.now()

                post = Post(title=title, url=url, description=description, creator = creator, created_on=created_on)
                post.save()
                return redirect('/')
        return render(request,'submit.html',{'form':form})
    return redirect('/signin')
</pre>



<p>This code is a Django view function that handles the submission of a new post. It first checks if the user is authenticated, and if they are not, it redirects them to the signin URL.</p>



<p>If the user is authenticated, it creates a new instance of a form called <code>PostForm</code>. It then checks if the request method is POST. If the form has been submitted, it creates a new instance of the <code>PostForm</code> with the data from the request.</p>



<p>It then checks if the form is valid. If it is, it retrieves the title, URL, and description from the form&#8217;s cleaned data and uses them to create a new Post object. It also sets the creator attribute of the post to the current user and sets the <code>created_on</code> attribute to the current date and time. It then saves the new post to the database and redirects the user to the homepage.</p>



<p>If the form is not valid or if the request method is not POST, meaning that the form has not been submitted, it returns a response that renders a template called <code>submit.html</code> and passes in the form to be displayed to the user.</p>



<p>Here is the <code>PostForm</code> class. Create a <code>forms.py</code> file and add it there.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django import forms
from .models import Post


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('title','url','description')
</pre>



<p>The <code>PostForm</code> class inherits from <code>forms.ModelForm</code> and defines a nested Meta class that specifies the model and fields to be used by the form.  A <code>ModelForm</code> allows you to create and update instances of a specific model.</p>



<p>In this case, the model attribute is set to <code>Post</code>, and the fields attribute is set to a tuple containing the fields title, URL, and description. This means that the form will include fields for these three attributes of the <code>Post</code> model.</p>



<p>When an instance of this form is created and validated, it can be used to create or update a Post object with the data entered by the user.</p>



<h3 class="wp-block-heading">Edit View</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def EditPostView(request,id):
    post = get_object_or_404(Post,id=id)
    if request.method =='POST':
        form = PostForm(request.POST, instance=post)
        if form.is_valid():
            form.save()
            return redirect('/')

    form = PostForm(instance =post)
    return render(request,'submit.html',{'form':form})
</pre>



<p>This view function handles the editing of an existing post. It takes two arguments: request and id. The id argument is used to retrieve the Post object that should be edited.</p>



<p>The function uses the <code>get_object_or_404</code> function to retrieve the Post object with the given id. If no such object exists, it raises a 404 error.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-398.png" alt="" class="wp-image-1529286" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-398.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-398-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>If the request method is POST, meaning that the form has been submitted, it creates a new instance of the <code>PostForm</code> with the data from the request and the instance parameter set to the retrieved Post object. It then checks if the form is valid. If it is, it saves the changes to the post and redirects the user to the homepage.</p>



<p>If the request method is not POST, meaning that the form has not been submitted, it creates a new instance of the <code>PostForm</code> with the instance parameter set to the retrieved Post object. This pre-populates the form fields with the current values of the post. It then returns a response that renders a template called submit.html and passes in the form to be displayed to the user.</p>



<p>Here are the <code>urlpatterns</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('submit', SubmitPostView, name='submit'),
path('edit/&lt;int:id>', EditPostView, name='edit'),
</pre>



<h3 class="wp-block-heading">Upvote and Downvote Views</h3>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from .models import Vote

def UpVoteView(request,id):
    if request.user.is_authenticated:
        post = Post.objects.get(id=id)
        votes = Vote.objects.filter(post = post)
        v = votes.filter(voter = request.user)
        if len(v) == 0:
            upvote = Vote(voter=request.user, post=post)
            upvote.save()
            return redirect('/')
    return redirect('/signin')
</pre>



<p>The function is used to handle upvoting a post by a user. Here’s what the code does:</p>



<ol class="wp-block-list" type="1">
<li>It checks if the user making the request is authenticated (i.e., logged in).</li>



<li>If the user is authenticated, it retrieves the post with the given&nbsp;id&nbsp;from the database.</li>



<li>It then retrieves all votes for that post from the database.</li>



<li>It checks if the user has already voted for that post by filtering the votes for that post by the current user.</li>



<li>If the user has not already voted for that post, it creates a new&nbsp;Vote&nbsp;object with the current user as the voter and the post as the post being voted for.</li>



<li>It then saves this new vote to the database.</li>



<li>Finally, it redirects the user to the homepage.</li>
</ol>



<p>If the user is not authenticated, it redirects them to the&nbsp;signin&nbsp;page.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def DownVoteView(request,id):
    if request.user.is_authenticated:
        post = Post.objects.get(id=id)
        votes = Vote.objects.filter(post = post)
        v = votes.filter(voter = request.user)
        if len(v) != 0:
            v.delete()
            return redirect('/')
    return redirect('/signin')
</pre>



<p>In this function, it checks if the user has already voted. If so, it deletes it. And then redirects them to the home page.</p>



<p>Finally, the <code>urlpatterns</code>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('vote/&lt;int:id>', UpVoteView, name='vote'),
path('downvote/&lt;int:id>', DownVoteView, name='dvote'),
</pre>



<h2 class="wp-block-heading">The Templates</h2>



<p>Please check the <a rel="noreferrer noopener" href="https://github.com/Jonaben1/django_hacker_news_clone" data-type="URL" data-id="https://github.com/Jonaben1/django_hacker_news_clone" target="_blank">source code</a> for the templates. They all go by the same explanation from the <a href="https://blog.finxter.com/how-i-added-more-views-to-the-hacker-news-clone-website/" data-type="post" data-id="1479921" target="_blank" rel="noreferrer noopener">previous series</a>. They all check if the user is authenticated before allowing them to benefit from the app’s functionalities.</p>



<p>From the templates, notice how the names given in the <code>urlpatterns</code> were used to refer to the URLs. All these were made possible using Django templating engine.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>We have come a long way in this Hacker News project created using the Django web framework. In the final part of this project, we will create views for the comment functionality. Thereafter, we test every feature of this app using information from the Hacker News website. If some features do not function as intended, we make the needed adjustments. Stay tuned!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="579" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-399-1024x579.png" alt="" class="wp-image-1529288" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-399-1024x579.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/07/image-399-300x169.png 300w, https://blog.finxter.com/wp-content/uploads/2023/07/image-399-768x434.png 768w, https://blog.finxter.com/wp-content/uploads/2023/07/image-399.png 1285w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Recommended</strong>: <a href="https://blog.finxter.com/how-i-coded-the-hacker-news-clone-in-django-web-application/" data-type="post" data-id="1460992" target="_blank" rel="noreferrer noopener">How I Coded a Hacker News Clone in Django</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-added-user-authentication-to-my-hacker-news-clone-django-website/">How I Added User Authentication to My Hacker News Clone Django Website</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Solved a Real-World Problem Using Monte Carlo Simulation</title>
		<link>https://blog.finxter.com/how-i-solved-a-real-world-problem-using-monte-carlo-simulation/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 27 Jul 2023 18:56:03 +0000</pubDate>
				<category><![CDATA[Data Science]]></category>
		<category><![CDATA[Data Visualization]]></category>
		<category><![CDATA[Matplotlib]]></category>
		<category><![CDATA[NumPy]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1529271</guid>

					<description><![CDATA[<p>In this project, you are taking the role of a data analyst. Your client, a large retail outlet has been running an affiliate marketing program in an effort to increase its sales. You are tasked to come up with a predictive model to predict how much should be budgeted for sales commission for the following ... <a title="How I Solved a Real-World Problem Using Monte Carlo Simulation" class="read-more" href="https://blog.finxter.com/how-i-solved-a-real-world-problem-using-monte-carlo-simulation/" aria-label="Read more about How I Solved a Real-World Problem Using Monte Carlo Simulation">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-solved-a-real-world-problem-using-monte-carlo-simulation/">How I Solved a Real-World Problem Using Monte Carlo Simulation</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>In this project, you are taking the role of a data analyst. Your client, a large retail outlet has been running an affiliate marketing program in an effort to increase its sales. You are tasked to come up with a predictive model to predict how much should be budgeted for sales commission for the following year.</em></p>



<p>This is one of the projects you will likely come across as a data analyst. How do you go about solving this problem? No doubt, you will ask your client for more information. For example, data showing previous years’ commission payments, the number of sales representatives, and the company’s defined formula for calculating commissions.</p>



<p>For this project, we assumed that the only information at our disposal is a rate schedule showing the company’s formula for calculating commissions.</p>



<h2 class="wp-block-heading">Rates Schedule</h2>



<figure class="wp-block-table is-style-stripes"><table><tbody><tr><td><strong>Sales ($)</strong></td><td><strong>Rates</strong></td></tr><tr><td>1,000 – 100,000</td><td>3%</td></tr><tr><td>101,000 – 500,000</td><td>5%</td></tr><tr><td>501,000 – 1,000,000</td><td>10%</td></tr></tbody></table></figure>



<p>The table shows that the more sales, the higher the commission rate. Since we were neither given sales historical data nor the number of sales representatives, we are going to make a few assumptions.</p>



<h2 class="wp-block-heading">Basic Assumptions</h2>



<p>We will generate&nbsp; random sales data based on the following assumptions which are also based on the information from the rates schedule:</p>



<ol class="wp-block-list" type="1">
<li>Sales made cannot be below 1000 dollars.</li>



<li>Sales made are in thousands.</li>



<li>The company employed 500 persons for the affiliate marketing program.</li>



<li>Sales made by each individual cannot be more than 1 million dollars in a given year.</li>
</ol>



<p>With these assumptions, we are ready to generate random data.</p>



<p>Python’s random module is used to <a href="https://blog.finxter.com/python-how-to-generate-a-random-number-with-a-specific-amount-of-digits/" data-type="post" data-id="720085" target="_blank" rel="noreferrer noopener">generate random numbers</a>. We will use the <code><a href="https://blog.finxter.com/pandas-dataframe-sample-method/" data-type="post" data-id="343727" target="_blank" rel="noreferrer noopener">sample()</a></code> method which takes in a range of numbers and generate random data based on the length defined.</p>



<p>The parameters for the <code>range()</code> function are given as: <code><a href="https://blog.finxter.com/python-range-function/" data-type="post" data-id="18290" target="_blank" rel="noreferrer noopener">range(start, stop, step)</a></code> where:</p>



<ol class="wp-block-list" type="a">
<li><code>start</code>: The starting point. In our case, it is 1000 as we assumed that the sales amount cannot be below 1000 dollars.</li>



<li><code>stop</code>: The ending point. In our case, it is 1 million. We assumed that it won’t go beyond that.</li>



<li><code>step</code>: The number to skip to ensure that the data end with three zeros as given in the rates schedule.</li>
</ol>



<p>The <code>sample()</code> method takes another parameter that indicates the length of the random numbers. Remember that each randomly generated number represents the sales made by each individual. So, the length will be 500 to indicate the number of workforces employed by the company.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import random

sales = random.sample(range(1000, 1000000, 1000), 500)
</pre>



<p>Let’s load the data on a Pandas DataFrame.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = pd.DataFrame({'Sales': sales})

data
0    986000
1    451000
2    487000
3    982000
4    194000
..      ...
495  761000
496  615000
497  786000
498  952000
499   82000

[500 rows x 1 columns]

data.Sales.min()
 2000

data.Sales.max()
986000
</pre>



<p>Now that we have our sales data. The next thing we have to do is to calculate the commission. The commission amount on the other hand is based on the rates. So, we need a way to assign rates for each sales representative based on sales made. A defined function will accomplish that.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def commissionRates(sales):
    if sales &lt;= 100000:
        return .03
    elif sales &lt;= 500000:
        return .05
    else:
        return .1
</pre>



<p>With this function defined, we can easily create the rates column using Pandas’ <code><a href="https://blog.finxter.com/the-pandas-apply-function/" data-type="post" data-id="37756" target="_blank" rel="noreferrer noopener">apply</a></code> function.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data['Rates'] = data.Sales.apply(commissionRates)
data.head(10)

       Sales   Rates
0  986000   0.10
1  451000   0.05
2  487000   0.05
3  982000   0.10
4  194000   0.05
5  305000   0.05
6  154000   0.05
7  768000   0.10
8  685000   0.10
9  885000   0.10
</pre>



<p>The rates are applied according to the rates schedule given to us. To get the commission amount, it’s a matter of multiplying the rates by the sales amount.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data['Commission'] = data.Sales * data.Rates
data.tail(10)

          Sales     Rates  Commission
490  149000   0.05      7450.0
491  793000   0.10     79300.0
492  205000   0.05     10250.0
493  894000   0.10     89400.0
494  276000   0.05     13800.0
495  761000   0.10     76100.0
496  615000   0.10     61500.0
497  786000   0.10     78600.0
498  952000   0.10     95200.0
499   82000   0.03      2460.0
</pre>



<p>We now have the total commission amount of $ 21,831,140 to be paid to sales representatives.</p>



<h2 class="wp-block-heading">Monte Carlo Simulation</h2>



<p>Monte Carlo analysis is a useful tool for making predictions. It takes as an input, different random numbers and runs them several times to generate many probable outcomes. How do we apply it in our case?</p>



<p>We want to predict the commission amount to be budgeted for the coming year. The amount we realized was based on one single attempt or iteration. We can’t just conclude that this is the ideal amount until we run it several times up to 10,000 or more using different randomly generated data.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def simulate_commission(iterations):
    results = []
    for i in range(iterations):
    sales = random.sample(range(1000, 1000000, 1000), 500)
    data = pd.DataFrame({'Sales': sales})
    data['Rates'] = data.Sales.apply(commissionRates)
    data['Commission'] = data.Sales * data.Rates
    results.append(
        [
        data.Sales.sum().round(),
        data.Commission.sum().round(),
        ]
    )
    
    return results
</pre>



<p>We create a function that will perform the simulation based on the number of times chosen. We can try 1,000, 10,000 or even 50,000 times. In the end, we sum the sales and the commissions to be used for further analysis.</p>



<p>Let’s give it a try with 5000 simulations and load it on a <a href="https://blog.finxter.com/pandas-dataframe-object-a-beginners-guide/" data-type="post" data-id="1511689" target="_blank" rel="noreferrer noopener">Pandas DataFrame</a>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">results = simulate_commission(5000)
results = pd.DataFrame.from_records(results, columns=[‘Sales’, ‘Commission’])

results
          Sales        Commission
0     256137000  22305150.0
1     252466000  21865310.0
2     246516000  21478230.0
3     250821000  21669860.0
4     252750000  22314280.0
...         ...         ...
4995  253876000  22073200.0
4996  245326000  21089810.0
4997  248717000  21651090.0
4998  246074000  21105970.0
4999  251908000  21810780.0

results.describe().round()
                  
                  Sales   Commission
count       5000.0      5000.0
mean   250092538.0  21826489.0
std      4526122.0    523127.0
min    229959000.0  19379090.0
25%    247034250.0  21476432.0
50%    250058000.0  21816840.0
75%    253203250.0  22188120.0
max    266212000.0  23649430.0
</pre>



<p>After running 5000 simulations, the results show that the commission amount is between $19M and $23M with a mean of $21M. This is within our previous results. Let’s visualize this on a <a href="https://blog.finxter.com/matplotlib-histogram/" data-type="post" data-id="5485" target="_blank" rel="noreferrer noopener">histogram</a>.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def currency(x, pos):
    if x >= 1e6:
        s = '${:1.1f}M'.format(x*1e-6)
    else:
        s = '${:1.0f}K'.format(x*1e-3)
    return s
</pre>



<p>Here, we are setting the function that will format the commission amount as it’s too large to be fitted on the chart. It will take the amount and the tick position as parameters. We will feed it into the <code>xaxis.set_major_formatter()</code> method to format the string.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import matplotlib.pyplot

fig, ax = plt.subplots()

ax.xaxis.set_major_formatter(currency)

results.Commission.plot(kind='hist', title='Commission Amount')

plt.grid()
plt.show()
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="714" height="401" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-393.png" alt="" class="wp-image-1529275" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-393.png 714w, https://blog.finxter.com/wp-content/uploads/2023/07/image-393-300x168.png 300w" sizes="auto, (max-width: 714px) 100vw, 714px" /></figure>
</div>


<p>Running the simulation 10,000 times produced the following result which is almost similar to the previous one.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="714" height="401" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-394.png" alt="" class="wp-image-1529276" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-394.png 714w, https://blog.finxter.com/wp-content/uploads/2023/07/image-394-300x168.png 300w" sizes="auto, (max-width: 714px) 100vw, 714px" /></figure>



<p>The mean is still between $21M and $22M, and the commission payment ranges between $19M and $24M.</p>



<p>These results no doubt give the managers of the retail outlet an estimate of how much should be budgeted for commission payment for the following year.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>We solved a real-world problem using Monte Carlo simulation – a tool used to gain a better understanding of distributions of probable outcomes. By calculating a formula multiple times using different random inputs, management can be able to make informed decisions.</p>



<p>This demonstration gives you an idea of how you can apply Monte Carlo simulation to solve more advanced problems.</p>
<p>The post <a href="https://blog.finxter.com/how-i-solved-a-real-world-problem-using-monte-carlo-simulation/">How I Solved a Real-World Problem Using Monte Carlo Simulation</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Made a Django Blog Audio Versions of My Blog Articles (Auto-Gen)</title>
		<link>https://blog.finxter.com/how-i-made-a-django-blog-audio-versions-of-my-blog-articles-auto-gen/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 27 Jul 2023 18:36:51 +0000</pubDate>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Text Processing]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1529224</guid>

					<description><![CDATA[<p>Creating a blog application not only helps us to practice our skills as a Django developer but it is also a way to share our programming knowledge. There are many people out there in different stages of their programming journey who will benefit from your wealth of experience. By blogging about your programming knowledge, you ... <a title="How I Made a Django Blog Audio Versions of My Blog Articles (Auto-Gen)" class="read-more" href="https://blog.finxter.com/how-i-made-a-django-blog-audio-versions-of-my-blog-articles-auto-gen/" aria-label="Read more about How I Made a Django Blog Audio Versions of My Blog Articles (Auto-Gen)">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-made-a-django-blog-audio-versions-of-my-blog-articles-auto-gen/">How I Made a Django Blog Audio Versions of My Blog Articles (Auto-Gen)</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Creating a blog application not only helps us to practice our skills as a Django developer but it is also a way to share our programming knowledge. There are many people out there in different stages of their programming journey who will benefit from your wealth of experience.</p>



<p>By blogging about your programming knowledge, you are helping both yourself and those who read your content. The step starts with creating and using a blog application proudly designed by you using any framework of your choice. This serves as living proof of your expertise in the programming niche you are blogging. </p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-388.png" alt="" class="wp-image-1529228" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-388.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-388-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>This is what we have done so far in this tutorial series. If you want to learn how we get to the stage we are right now, you do well to start from the beginning<sup>1</sup> of this tutorial series.</p>



<p>In this tutorial, we are going to add more features to our blog application to make it look more robust. Specifically, we are going to:</p>



<ol class="wp-block-list" type="1">
<li>Create a dark mode toggler;</li>



<li>Add reading time on each page;</li>



<li>Add an option to listen to an audio version of our content;</li>
</ol>



<p>This helps to improve user experience. We have a lot of coding to do. Don’t just sit down there! Follow along with me and get your hands dirty with this hands-on practical project.</p>



<h2 class="wp-block-heading">Adding reading time on each page</h2>



<p>Believe it or not, time is a very precious and scarce commodity. There is a saying that time is money. Hence, you don’t joke with people’s time. When readers visit your blog, they would like to know how long it will take them to read your content. When they see you always display the reading time, they will likely come back to your website.</p>



<p>How can we add a reading time to our blog application? You can either use JavaScript or Python. It’s a matter of defining how many words per minute (WPM). <a href="https://psyarxiv.com/xynwg/" data-type="URL" data-id="https://psyarxiv.com/xynwg/" target="_blank" rel="noreferrer noopener">Studies</a> have shown that the average reading speed of an adult is 238 WPM. Thus, to check the reading time of 500-word text, divide it by 238. The result will be in minutes.</p>



<p>500 / 238 = 2.10</p>



<p>2.10 * 60 = 126 seconds or 2 mins 6 seconds</p>



<p>This is exactly the formula we will use except that we will go by 250WPM which is mostly used.</p>



<p>Open the Django shell let’s demonstrate how to do so with Python.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-389.png" alt="" class="wp-image-1529229" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-389.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-389-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>We split the text separated by space, and get its length. Then, we divide it by 250.</p>



<p>Go to the Post model in your <code>models.py</code> file. Create a method that will do the same thing we did above.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class Post(models.Model):
    …

    def read_time(self):
        return round(len(self.body.split(' ')) / 250)
</pre>



<p>The body field is where the blog content is written. It will split each word separated by space and get the length which is then divided by 250. The result is rounded up to the nearest minute. Wherever this method is called on the application, the reading time is displayed.</p>



<p>To display the reading time, go to the <code>blog_detail</code> template. Check where you will see the following and add the method to it.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;p class=" text-muted">{{ post.author }} | {{ post.created_on }} | Reading Time: {{ post.read_time }} Mins&lt;/p></pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-390.png" alt="" class="wp-image-1529232" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-390.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-390-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p><sup>&nbsp;</sup>Now, all your blog pages will have the reading time displayed. As simple as that.</p>



<h2 class="wp-block-heading">Toggling Dark Mode</h2>



<p>I like surfing the net with dark mode toggled. I wonder why some webmasters can’t implement such a simple feature on their web pages. This helps to reduce eye strain. Let’s get straight ahead to add this feature using JavaScript. First of all, add this to <code>base.html</code> just after the link to the homepage:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;button id="mode" onclick="toggler()">Night Mode&lt;/button></pre>



<p>Once the button is clicked the <code>toggler()</code> function will be executed. On the bottom after the body tag, add a link to a JavaScript file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;script src="{% static 'js/index.js' %}">&lt;/script></pre>



<p>Note that the JavaScript function to be implemented will not work if the script comes before the <code>button</code> element. Next, add this to the <code>styles.css</code> file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">  #mode {
            float: right;
        }

        body.dark-mode {
           background: black;
           color: white;
        }

        body.dark-mode header {
           background: black;
           color: white;
        }


       body.dark-mode .container .card p {
           background: black;
           border-color: black;
           color: black;
       }

      body.dark-mode .container .card {
           background: black;
           border-color: black;
     }

     body.dark-mode .container .card .card-body {
           color: white;
      }
</pre>



<p>Here, we create a dark-mode CSS class name that will be called when the dark mode is toggled. We use the CSS float property to move the button to the right. We overwrite the Bootstrap to make sure that the white border is removed.</p>



<p>Next, create a js folder and a <code>script.js</code> file inside the folder. The js folder should be inside the static folder.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">toggler = () => {
    let element = document.getElementById('mode');
    let body = document.body;
    if (element.innerHTML === 'Night Mode') {
       element.innerHTML = 'Light Mode';
       body.classList.toggle('dark-mode');
       
    } else {
        element.innerHTML = 'Night Mode';
        body.classList.toggle('dark-mode');
    }
}
</pre>



<p>If the text in the button is strictly ‘Night Mode’, it will change the text to ‘Light Mode, and toggle the night mode by calling the dark-mode CSS class name.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="725" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-391.png" alt="" class="wp-image-1529238" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-391.png 725w, https://blog.finxter.com/wp-content/uploads/2023/07/image-391-300x169.png 300w" sizes="auto, (max-width: 725px) 100vw, 725px" /></figure>
</div>


<h2 class="wp-block-heading">Adding an audio version of the content</h2>



<p>To add audio to our blog app, we will use <a href="https://blog.finxter.com/better-than-openai-whisper-googles-new-speech-recognition-api/" data-type="post" data-id="1254506" target="_blank" rel="noreferrer noopener">Google’s text-to-speech library</a>. We will modify the <code>blog_detail</code> view function to generate an audio file and pass it to a template.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from gtts import gTTS
from django.core.files.storage import default_storage
from django.core.files.base import ContentFile
from django.conf import settings
import os

def blog_detail(request, slug):
    post = get_object_or_404(Post, slug=slug)
    comments = post.comments.filter(active=True)
    new_comments = None
    if request.method == 'POST':
        comment_form = CommentForm(data=request.POST)
        if comment_form.is_valid():
            # create object but don't save to database yet
            new_comment = comment_form.save(commit=False)
            # assign the current post to the comment
            new_comment.post = post
            # save the comment to the database
            new_comment.save()
    else:
        comment_form = CommentForm()

    # Convert the text content of the blog post to speech using gTTS
    tts = gTTS(text=post.body, lang='en')
    audio_file_name = f"{post.slug}.mp3"
    audio_folder_path = os.path.join(settings.MEDIA_ROOT, 'audio')
    os.makedirs(audio_folder_path, exist_ok=True)
    audio_file_path = os.path.join(audio_folder_path, audio_file_name)
    tts.save(audio_file_path)

    # Save the audio file to the default storage (e.g. local disk or cloud storage)
    with open(audio_file_path, 'rb') as f:
        default_storage.save(f"audio/{audio_file_name}", ContentFile(f.read()))

    # Pass the URL of the audio file to the template
    context = {
        'post': post,
        'comments': comments,
        'new_comments': new_comments,
        'comment_form': comment_form, 
           'audio_file_url': default_storage.url(f"audio/{audio_file_name}")
    }

    return render(request, 'blog_detail.html', context)
</pre>



<p>This code creates an audio folder within your media directory using the <code>os.makedirs()</code> function. The generated MP3 file is saved in this folder and its URL is passed to the template through the context dictionary.</p>



<p>In your template, you can use the&nbsp;<code>audio_file_url</code>&nbsp;variable to create an&nbsp;<code>&lt;audio&gt;</code>&nbsp;element that plays the generated audio file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;audio controls>
  &lt;source src="{{ audio_file_url }}" type="audio/mpeg">
  Your browser does not support the audio element.
&lt;/audio>
</pre>



<p>This code creates an <code>&lt;audio&gt;</code> element with a <code>&lt;source&gt;</code> element that specifies the URL of the audio file. The controls attribute adds playback controls to the audio player.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-392.png" alt="" class="wp-image-1529247" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-392.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-392-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>You can see it from the screenshot. Once you hit the play button, it will play the blog content. This audio will be visible on every blog page. Unlike the previous screenshot, I haven’t yet formatted this page. If you want to learn how I showed you how to format your blog page, <a href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django-part-4/" data-type="post" data-id="1461023" target="_blank" rel="noreferrer noopener">check out this article</a>.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>No doubt, this tutorial has been an interesting one. We added three features to our Django blog application to improve user experience. Our blog is fully ready to be used to share our programming knowledge. Or is it?</p>



<p>Speaking about sharing, there are no share buttons to share to social media sites. There are no like buttons too. Moreover, I decided that there’s no need to integrate user authentication. There are <a href="https://blog.finxter.com/how-i-added-a-user-authentication-to-my-django-real-estate-application/" data-type="post" data-id="1479871" target="_blank" rel="noreferrer noopener">many projects</a> on that if you want to learn more.</p>



<p>What about migrating to a different database and deploying to a production server? So, you can see that our Django blog is not yet ready until it is ready.</p>
<p>The post <a href="https://blog.finxter.com/how-i-made-a-django-blog-audio-versions-of-my-blog-articles-auto-gen/">How I Made a Django Blog Audio Versions of My Blog Articles (Auto-Gen)</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Created Charts Using Highcharts.js in Django Web Application</title>
		<link>https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 27 Jul 2023 18:03:05 +0000</pubDate>
				<category><![CDATA[Data Science]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1529193</guid>

					<description><![CDATA[<p>Highcharts.js is a client-side JavaScript library used for data visualization. It can be included in Django templates just like any other JavaScript library using the link: The hard work has already been done for us by Highcharts. Where we need to work on is finding a way to structure or format the data in a ... <a title="How I Created Charts Using Highcharts.js in Django Web Application" class="read-more" href="https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/" aria-label="Read more about How I Created Charts Using Highcharts.js in Django Web Application">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/">How I Created Charts Using Highcharts.js in Django Web Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p></p>



<p>Highcharts.js is a client-side JavaScript library used for data visualization. It can be included in Django templates just like any other JavaScript library using the link:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;script src="https://code.highcharts.com/highcharts.src.js">&lt;/script></pre>



<p>The hard work has already been done for us by Highcharts. Where we need to work on is finding a way to structure or format the data in a way that Highcharts can understand. In this tutorial, we will learn how to dynamically generate charts and have them rendered on a Django web application.</p>



<h2 class="wp-block-heading">The Model</h2>



<p>For this demonstration, we will use the famous Titanic dataset. Here is the model class:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">SEX_CHOICES = (
    ('M', 'Male'),
    ('F', 'Female'),
)


PORT_CHOICES = (
    ('C', 'Cherbourg'),
    ('Q', 'Queenstown'),
    ('S', 'Southampton'),
)

class Passenger(models.Model):
    name = models.CharField(max_length=100, blank=True)
    sex = models.CharField(max_length=1, choices=SEX_CHOICES)
    survived = models.BooleanField(default=True)
    age = models.FloatField(null=True)
    p_class = models.CharField(max_length=10)
    fare = models.FloatField(null=True)
    embarked = models.CharField(max_length=1, choices=PORT_CHOICES)

    def __str__(self):
        return self.name
</pre>



<p>The dataset can be accessed on my <a rel="noreferrer noopener" href="https://github.com/Jonaben1/highcharts_with_django.git" data-type="URL" data-id="https://github.com/Jonaben1/highcharts_with_django.git" target="_blank">GitHub</a> page. Of course, there are more columns than the ones in the <code>Passenger</code> class. But these are the ones we will use.</p>



<p>In previous tutorials, I have worked with the Titanic dataset to <a href="https://blog.finxter.com/how-i-created-a-machine-learning-web-application-using-django/" data-type="post" data-id="1242421" target="_blank" rel="noreferrer noopener">create a Machine Learning web application</a> that predicts the survival of passengers based on their attributes. We won’t be performing any data manipulation with the dataset in this tutorial.</p>



<p>We will only query the database to display the data using Highcharts so that we can see how Django interacts with Highcharts.</p>



<h2 class="wp-block-heading">Populating the Database</h2>



<p>Now that we have created the <code>Model</code> class and performed migrations (do it if you have not already done so), we need a way to populate the database with the Titanic dataset.</p>



<p>There are so many ways to do so. We can use the <code>django-csvimport</code> or <code>django-adaptor</code> library which allows us to easily transform a CSV file into a model instance.</p>



<p>Once we install the library, add it to the <code>INSTALLED _APPS</code> section, and run the migration command. The library will match the header line of the CSV file with the fields in the selected model and import any rows that include all required fields.</p>



<p>Another way to populate the database is to use the inbuilt <code>csv</code> module. This is the method we will use. Herein lies the steps we will follow in the Django shell:</p>



<ul class="wp-block-list">
<li>Open the CSV file using Python’s built-in <code><a href="https://blog.finxter.com/python-open-function/" data-type="post" data-id="24793" target="_blank" rel="noreferrer noopener">open()</a></code> function</li>



<li>Create a <code>csv.reader</code> object to read the data from the CSV file</li>



<li>Iterate over the rows in the CSV file using a <code>for</code> loop</li>



<li>For each row, use the Django’s <code>get_or_create</code> method to create a new record in the database.</li>
</ul>



<p>Run the code below on your terminal to open the Django shell.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">python3 manage.py shell</pre>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">with open('titanic.csv', newline='') as csvfile:
    reader = csv.reader(csvfile)
    next(reader)  # Skip the header row
    for row in reader:
        # Check if any of the values are empty
        if not all(row[2:5] + row[7:11]):
            continue  # Skip this row
        passenger = Passenger(
            name=row[2],
            sex=row[3],
            survived=bool(int(row[1])),
            age=float(row[4],
            p_class=row[0],
            fare=row[8],
            embarked=row[10]
        )
        passenger.save()
</pre>



<p>The code reads the data from the file, creates a new&nbsp;<code>Passenger</code>&nbsp;object for each row, and saves it to the database.</p>



<p>We use the&nbsp;<code>all()</code>&nbsp;function to check if all of the values in the columns that correspond to the fields in the&nbsp;<code>Passenger</code>&nbsp;model are not empty. If any of these values are empty, we use the&nbsp;<code>continue</code>&nbsp;statement to skip the current row and move on to the next row. This will skip any rows with missing values in any of these columns.</p>



<p>Having populated the database, let’s check the admin panel to see the results. Be sure to register the model in the <code>admin.py</code> file.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-380.png" alt="" class="wp-image-1529204" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-380.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-380-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>Can you see it? The database has been automatically populated with the Titanic dataset! It’s now time to proceed with the very task that forms the basis of this project.</p>



<h2 class="wp-block-heading">Querying the database to display charts</h2>



<p>As rightly stated, for Highcharts to interact with Django, the data must be formatted in a way it will understand. This can be done by querying the database. Therefore, in this project, we will query the database to:</p>



<ol class="wp-block-list" type="1">
<li>Display the number of Titanic survivors and death by ticket class.</li>



<li>Display the number of Titanic survivors and death by gender.</li>



<li>Display the number of Titanic survivors and death by age group.</li>
</ol>



<h2 class="wp-block-heading">Titanic Survivors by Ticket class</h2>



<p>Go to the <code>views.py</code> file and write this code:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.shortcuts import render
from .models import Passenger
import json


def survivors_by_ticket_class(request):
    dataset = []
    for ticket_class in Passenger.objects.values_list('p_class', flat=True).distinct():
        survived_count = Passenger.objects.filter(p_class=ticket_class, survived=True).count()
        not_survived_count = Passenger.objects.filter(p_class=ticket_class, survived=False).count()
        dataset.append({
            'ticket_class': ticket_class,
            'survived_count': survived_count,
            'not_survived_count': not_survived_count
        })


    survivors = {
        'name': 'Survived',
        'data': [data['survived_count'] for data in dataset],
        'color': 'green'
    }

    death = {
        'name': 'Not Survived',
        'data': [data['not_survived_count'] for data in dataset],
        'color': 'red'
    }


    chart = {
        'chart': {'type': 'column'},
        'title': {'text': 'Titanic Survivors by Ticket Class'},
        'xAxis': {'categories': [data['ticket_class'] for data in dataset]},
        'series': [survivors, death]
    }

    dump = json.dumps(chart)

    return render(request, 'ticket_class.html', {'chart': dump})
</pre>



<p>We initialize an <a href="https://blog.finxter.com/how-to-create-an-empty-list-in-python/" data-type="post" data-id="453870" target="_blank" rel="noreferrer noopener">empty list</a> and iterate over the distinct value of the <code>p_class</code> field in the <code>Passenger</code> model. Then, we count the number of passengers that survived and those that do not. Finally, we <a href="https://blog.finxter.com/how-to-create-a-dictionary-from-two-lists/" data-type="post" data-id="316802" target="_blank" rel="noreferrer noopener">create a dictionary</a> and append it to the dataset list. The dataset now becomes a list of dictionaries.</p>



<p>This is the result stored in the dataset list:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[{'ticket_class': '1', 'survived_count': 156, 'not_survived_count': 80},
 {'ticket_class': '2', 'survived_count': 16, 'not_survived_count': 5},
 {'ticket_class': '3', 'survived_count': 8, 'not_survived_count': 5}]
</pre>



<p>Remember, we skip some rows of the Titanic dataset. The chart configuration is done at the backend in the view function.</p>



<p>The <code>survivors</code> and <code>death</code> dictionaries represent the two data series that will be plotted on the chart. The <code>name</code> key specifies the name of the series, the <code>data</code> key specifies the data values for the series, and the <code>color</code> key specifies the color of the columns for the series.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-381.png" alt="" class="wp-image-1529205" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-381.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-381-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>The&nbsp;<code>chart</code>&nbsp;dictionary contains the overall configuration for the chart. The&nbsp;<code>'chart': {'type': 'column'}</code>&nbsp;key-value pair specifies that this is a column chart. The&nbsp;<code>'title': {'text': 'Titanic Survivors by Ticket Class'}</code>&nbsp;key-value pair specifies the title of the chart.</p>



<p>The&nbsp;<code>'xAxis': {'categories': [data['ticket_class'] for data in dataset]}</code>&nbsp;key-value pair specifies the categories for the x-axis of the chart, which in this case are the ticket classes. Finally, the&nbsp;<code>'series': [survivors, death]</code>&nbsp;key-value pair specifies that the&nbsp;<code>survivors</code>&nbsp;and&nbsp;<code>death</code>&nbsp;data series should be plotted on the chart.</p>



<p>The <code>json.dumps()</code> function is used to convert the <code>chart</code> dictionary into a JSON-formatted string. This is necessary because the data needs to be in a format that can be easily passed to the template and rendered in the browser. </p>



<p>Here is the template:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;!doctype html>
&lt;html>
&lt;head>
  &lt;meta charset="utf-8">
  &lt;title>Django Highcharts Example&lt;/title>
&lt;/head>
&lt;body>
  &lt;div id="container">&lt;/div>
  &lt;script src="https://code.highcharts.com/highcharts.src.js">&lt;/script>
  &lt;script>
    Highcharts.chart('container', {{ chart|safe }});
  &lt;/script>
&lt;/body>
&lt;/html>
</pre>



<p>The&nbsp;<code>{{ chart|safe }}</code>&nbsp;code is using the&nbsp;<code>safe</code>&nbsp;keyword to mark the&nbsp;<code>chart</code>&nbsp;variable as safe for rendering as HTML. This is necessary because the&nbsp;<code>chart</code>&nbsp;variable contains a JSON-formatted string that needs to be rendered the way it is written for the charting library to correctly parse and use it.</p>



<p>Without the&nbsp;<code>safe</code>&nbsp;keyword, any special characters in the&nbsp;<code>chart</code>&nbsp;variable would be escaped, which would prevent the charting library from correctly parsing the data and creating the chart.</p>



<h2 class="wp-block-heading">Titanic survivors by gender</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.db.models import Count, Q
from .models import Passenger

def survivors_by_gender(request):
    dataset = Passenger.objects \
        .values('sex') \
        .annotate(survived_count=Count('sex', filter=Q(survived=True)),
                  not_survived_count=Count('sex', filter=Q(survived=False))) \
        .order_by('sex')

    survivors = {
        'name': 'Survived',
        'data': [data['survived_count'] for data in dataset],
        'color': 'green'
    }

    death = {
        'name': 'Not Survived',
        'data': [data['not_survived_count'] for data in dataset],
        'color': 'red'
    }

    chart = {
        'chart': {'type': 'column'},
        'title': {'text': 'Titanic Survivors by Gender'},
        'xAxis': {'categories': [data['sex'] for data in dataset]},
        'series': [survivors, death]
    }

    dump = json.dumps(chart)

    return render(request, 'gender.html', {'chart': dump})
</pre>



<p>This function uses the provided code to create a <code>dataset</code> of the number of survivors and deaths by gender. In Django, the <code>annotate()</code> method is used to calculate aggregate values for each item in a queryset. It allows you to add additional fields to the queryset that represent the result of an aggregation, such as a count, sum, average, minimum, or maximum.</p>



<p>`<code>Q</code>` is a class in Django that allows you to create complex lookups by combining multiple query expressions using logical operators such as `<code>&amp;</code>` (and), `<code>|</code>` (or), and `<code>~</code>` (not). It is often used in conjunction with the `<code><a href="https://blog.finxter.com/python-filter/" data-type="post" data-id="22487" target="_blank" rel="noreferrer noopener">filter()</a></code>` method to create more complex queries.</p>



<p>The rest of the code is similar to the previous function, but with some changes to reflect the fact that the data is now grouped by gender instead of ticket class.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-382.png" alt="" class="wp-image-1529208" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-382.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-382-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>Check my <a href="https://github.com/Jonaben1/highcharts_with_django.git" data-type="URL" data-id="https://github.com/Jonaben1/highcharts_with_django.git" target="_blank" rel="noreferrer noopener">GitHub</a> page for the templates and the app-level URLs. They are basically the same.</p>



<h2 class="wp-block-heading">Titanic survivors by age</h2>



<p>Back to the <code>views.py</code> file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.db.models import  F, ExpressionWrapper, IntegerField
def survivors_by_age(request):
    dataset = Passenger.objects \
        .annotate(age_bin=ExpressionWrapper((F('age')/10)*10, output_field=IntegerField())) \
        .values('age_bin') \
        .annotate(survived_count=Count('age_bin', filter=Q(survived=True)),
                  not_survived_count=Count('age_bin', filter=Q(survived=False))) \
        .order_by('age_bin')

    survivors = {
        'name': 'Survived',
        'data': [data['survived_count'] for data in dataset],
        'color': 'green'
    }

    death = {
        'name': 'Not Survived',
        'data': [data['not_survived_count'] for data in dataset],
        'color': 'red'
    }

    chart = {
        'chart': {'type': 'column'},
        'title': {'text': 'Titanic Survivors by Age Group'},
        'xAxis': {'categories': [f"{int(data['age_bin'])}s" for data in dataset]},
        'series': [survivors, death]
    }

    dump = json.dumps(chart)

    return render(request, 'age.html', {'chart': dump})
</pre>



<p>The F class is used to reference fields on a model within a query. In the code above, we are referencing the age field. <code>ExpressionWrapper</code>&nbsp;is a class that allows you to wrap a database expression with a specific output field. It is used to perform calculations on a field and use the result in a query.</p>



<p>In the code,&nbsp;<code>ExpressionWrapper((F('age')/10)*10, output_field=IntegerField())</code>&nbsp;is used to create an expression that calculates the age group for each passenger.</p>



<p><code>IntegerField</code> is a class that represents an integer field in a database. It is used as the <code>output_field</code> argument for the <code>ExpressionWrapper</code> to specify that the result of the expression should be treated as an integer.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-383.png" alt="" class="wp-image-1529211" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-383.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-383-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>Those three classes are provided by Django ORM to help with constructing complex database queries.</p>



<p>We can go on and on to create complex queries. Check my GitHub page to see more views created to:</p>



<p><strong>Display Titanic survivors by location</strong></p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-384.png" alt="" class="wp-image-1529212" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-384.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-384-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>



<p><strong>Average age by ticket class</strong></p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-385.png" alt="" class="wp-image-1529213" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-385.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-385-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p><strong>Total fare paid by passengers in each ticket class</strong></p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-386.png" alt="" class="wp-image-1529214" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-386.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-386-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p><strong>The minimum and maximum age of passengers in each ticket class</strong></p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-387.png" alt="" class="wp-image-1529215" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-387.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-387-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<h2 class="wp-block-heading">Conclusion</h2>



<p>In this tutorial, we have learned how to use the Django ORM to create complex queries that aggregate data from a model. We have also learned how to use this data to create charts using Highcharts.js.</p>



<p>Specifically, we learned how to populate our database with data from a CSV file. We have created several functions that generate charts showing various statistics about the Titanic passengers, such as the number of survivors by ticket class, gender, and port of embarkation, as well as the average age and total fare paid by ticket class.</p>



<p>Overall, this tutorial has demonstrated the power and flexibility of the Django ORM and shown how it can be used to create data-driven visualizations with Highcharts.js.</p>
<p>The post <a href="https://blog.finxter.com/how-i-created-charts-using-highcharts-js-in-django-web-application/">How I Created Charts Using Highcharts.js in Django Web Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Creating an About Us Page in Python Django</title>
		<link>https://blog.finxter.com/creating-an-about-us-page-in-python-django/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 13 Jul 2023 19:31:52 +0000</pubDate>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1496237</guid>

					<description><![CDATA[<p>General Solution Creating an &#8220;About Us&#8221; page in Django involves optionally creating a new app, and then defining a view to render the page. You then create a URL for the view and an HTML template for the page content. Finally, you run the server to view your &#8220;About Us&#8221; page. Step 1: Create a ... <a title="Creating an About Us Page in Python Django" class="read-more" href="https://blog.finxter.com/creating-an-about-us-page-in-python-django/" aria-label="Read more about Creating an About Us Page in Python Django">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/creating-an-about-us-page-in-python-django/">Creating an About Us Page in Python Django</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">General Solution</h2>



<p class="has-global-color-8-background-color has-background">Creating an &#8220;About Us&#8221; page in Django involves optionally creating a new app, and then defining a view to render the page. You then create a URL for the view and an HTML template for the page content. Finally, you run the server to view your &#8220;About Us&#8221; page.</p>



<h3 class="wp-block-heading">Step 1: Create a New Django App (Optional)</h3>



<p>If you want to keep your project organized, you can create a new app for your &#8220;About Us&#8221; page. In your terminal, navigate to your Django project directory and run the following command: <code>python manage.py startapp about</code>.</p>



<h3 class="wp-block-heading">Step 2: Add the App to Your Project Settings (If a New App is Created)</h3>



<p>Open your Django project&#8217;s settings file (usually <code>settings.py</code>) and add your new app to the <code>INSTALLED_APPS</code> list.</p>



<h3 class="wp-block-heading">Step 3: Create a View for the Page</h3>



<p>In the <code>views.py</code> file of your app, create a view for your page:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.shortcuts import render

def about_view(request):
    return render(request, 'about/about.html')
</pre>



<p>This view will render the &#8220;About Us&#8221; page when the page is visited.</p>



<h3 class="wp-block-heading">Step 4: Create a URL for the View</h3>



<p>In the <code>urls.py</code> file of your app, create a URL for your view:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.urls import path
from .views import about_view

urlpatterns = [
    path('about/', about_view, name='about'),
]
</pre>



<h3 class="wp-block-heading">Step 5: Create a Template for the Page</h3>



<p>In your app&#8217;s templates directory (you might need to create it), create a new directory named &#8216;<code>about</code>&#8216; and inside it, create an HTML file: <code>about.html</code>. This file should contain the HTML for your &#8220;About Us&#8221; page.</p>



<h3 class="wp-block-heading">Step 6: Run the Server</h3>



<p>Finally, run your server with <code>python manage.py runserver</code> and visit <code>http://localhost:8000/about/</code> to see your &#8220;About Us&#8221; page.</p>



<p>Remember to replace &#8216;about&#8217; with the actual name of your app if it&#8217;s different. This is a very basic example. In a real-world application, you might want to add more features, like dynamic content, images, etc.</p>



<h2 class="wp-block-heading">Example</h2>



<p>The ‘About’ or ‘About Us’ page contains information about the purpose and goals of your blog. It should also include your background and expertise in the selected niche and other relevant information to help readers understand your blog.</p>



<p>Let’s create the <code>about.html</code> template.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{% extends 'base.html' %}
{% block content %}

&lt;div class="container">
  &lt;div class="row">
    &lt;div class="col-md-8 card mb-4  mt-3 left  top">
      &lt;div class="card-body">
          &lt;h1>About Us&lt;/h1>
          &lt;p class="card-text">I created this blog to share tips, suggestions and practical advice on how to maintain good health&lt;/p>
          &lt;p class="card-text">I'm not a health expert but I am passionate about the topic and committed to providing accurate and reliable information.&lt;/p>
          &lt;p class="card-text">Any suggestion is highly welcome. Feel free to &lt;a href="{% url 'contact' %}">contact me&lt;/a> for more information or to say hello.&lt;/p>
      &lt;/div>
    &lt;/div>
  &lt;/div>
&lt;/div>
{% endblock %}
</pre>



<p>As usual, we extend the base template. Inside the block, we write what our blog is all about. Notice how we link the contact page using Django template engine’s <code>{% url … %}</code> tag. Within it, we use the target name we specified earlier in the <code>urls.py</code> file.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-164.png" alt="" class="wp-image-1496238" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-164.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-164-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>We want this ‘About’ page to appear on every post. So, we will include it at the footer of the base template.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;footer class="py-3 bg-grey">
            &lt;p class="m-0 text-dark text-center ">Copyright &amp;copy; Django Blog&lt;/p>
            &lt;p class="m-0 text-dark text-center">&lt;a href="{% url 'about' %}">About Us&lt;/a>&lt;/p>
  &lt;/footer>
</pre>



<p>So, from the About page, we can see a link to the contact page. You can as well add a link to your social media pages. For the view function, it’s pretty straightforward.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def about(request):
    return render(request, 'about.html')
</pre>



<p>Then, the endpoint:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('about', about, name='about'),</pre>



<p>Check out the <a href="https://github.com/Jonaben1/django_blog" data-type="URL" data-id="https://github.com/Jonaben1/django_blog" target="_blank" rel="noreferrer noopener">GitHub repository</a> for the full code of my portfolio app and the beginning of my tutorial series if you haven&#8217;t already:</p>



<p class="has-base-2-background-color has-background"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f469-200d-1f4bb.png" alt="👩‍💻" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Recommended</strong>: <a href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django/" data-type="post" data-id="1332381" target="_blank" rel="noreferrer noopener">Python Django Portfolio App &#8211; How I Made It</a></p>



<p>The post <a href="https://blog.finxter.com/creating-an-about-us-page-in-python-django/">Creating an About Us Page in Python Django</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Created a Simple Contact Page in Python Django</title>
		<link>https://blog.finxter.com/how-i-created-a-simple-contact-page-in-python-django/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Thu, 13 Jul 2023 19:14:54 +0000</pubDate>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1496223</guid>

					<description><![CDATA[<p>High-Level Approach Creating a contact page in Django involves creating a new app, adding it to the project settings, and defining a model for the contact form. You then create a form for the model, a view to handle form submission and display, and a URL for the view. Finally, you create templates for the ... <a title="How I Created a Simple Contact Page in Python Django" class="read-more" href="https://blog.finxter.com/how-i-created-a-simple-contact-page-in-python-django/" aria-label="Read more about How I Created a Simple Contact Page in Python Django">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-a-simple-contact-page-in-python-django/">How I Created a Simple Contact Page in Python Django</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">High-Level Approach</h2>



<p class="has-global-color-8-background-color has-background">Creating a contact page in Django involves creating a new app, adding it to the project settings, and defining a model for the contact form. You then create a form for the model, a view to handle form submission and display, and a URL for the view. Finally, you create templates for the form and a success page, and run the server to view your contact form.</p>



<p>Here&#8217;s a step-by-step guide:</p>



<h3 class="wp-block-heading">Step 1: Create a new Django app</h3>



<p>First, you need to create a new Django app. In your terminal, navigate to your Django project directory and run the following command:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">python manage.py startapp contact
</pre>



<p>This will create a new Django app named &#8216;<code>contact</code>&#8216;.</p>



<h3 class="wp-block-heading">Step 2:  Add the app to your project settings</h3>



<p>Open your Django project&#8217;s settings file (usually <code>settings.py</code>) and add your new app to the <code>INSTALLED_APPS</code> list:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">INSTALLED_APPS = [
    ...
    'contact',
    ...
]
</pre>



<h3 class="wp-block-heading">Step 3: Create a model for the contact form</h3>



<p>In the <code>models.py</code> file of your new app, create a model for the contact form. This model will define the fields of the form. </p>



<p>Here&#8217;s a basic example:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    message = models.TextField()
</pre>



<h3 class="wp-block-heading">Step 4: Create a form for the model</h3>



<p>In the same directory, create a new file named <code>forms.py</code> and define a form for your model:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = ['name', 'email', 'message']
</pre>



<h3 class="wp-block-heading">Step 5: Create a view for the form</h3>



<p>In the <code>views.py</code> file of your app, create a view for your form:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.shortcuts import render
from .forms import ContactForm

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            form.save()
            return render(request, 'contact/success.html')
    else:
        form = ContactForm()
    return render(request, 'contact/contact.html', {'form': form})
</pre>



<p>This view will display the contact form when the page is visited, and it will save the form data when the form is submitted.</p>



<h3 class="wp-block-heading">Step 6: Create a URL for the view</h3>



<p>In the <code>urls.py</code> file of your app, create a URL for your view:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.urls import path
from .views import contact_view

urlpatterns = [
    path('contact/', contact_view, name='contact'),
]
</pre>



<h3 class="wp-block-heading">Step 7: Create templates for the form and the success page</h3>



<p>In your app&#8217;s templates directory (you might need to create it), create a new directory named &#8216;contact&#8217; and inside it, create two HTML files: <code>contact.html</code> and <code>success.html</code>. The <code>contact.html</code> file should contain the form, and the <code>success.html</code> file should contain a message that will be displayed when the form is successfully submitted.</p>



<h3 class="wp-block-heading">Step 8: Run the server</h3>



<p>Finally, run your server with <code>python manage.py runserver</code> and visit <code>http://localhost:8000/contact/</code> to see your contact form.</p>



<p>Remember to replace &#8216;<code>contact</code>&#8216; with the actual name of your app if it&#8217;s different. Also, this is a very basic example. In a real-world application, you would probably want to add more features, like sending an email when the form is submitted, validating the form data, etc.</p>



<h2 class="wp-block-heading">Example: Portfolio Website Django</h2>



<p>We will create a contact page so anyone who wants to pass information or suggestions can reach us. We have already <a href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django-part-4/" data-type="post" data-id="1461023" target="_blank" rel="noreferrer noopener">created a contact page</a> while building a <a rel="noreferrer noopener" href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django/" data-type="post" data-id="1332381" target="_blank">portfolio website</a> using Django. Please go through that tutorial for more explanation because we will do exactly what we did there.</p>



<p>Add this <code>Contact</code> class to your <code>models.py</code> file:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from datetime import datetime

class Contact(models.Model):
    name = models.CharField(max_length=50)
    subject = models.CharField(max_length=200)
    email = models.EmailField()
    submitted_on = models.DateTimeField(default=datetime.now)
    message = models.TextField()

    def __str__(self):
        return self.name
</pre>



<p>Perform migrations and proceed to create a <code>ContactForm</code> class in your <code>forms.py</code> file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class ContactForm(forms.ModelForm):
    name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Name'}))
    email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'}))
    subject = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Subject'}))
    message = forms.CharField(widget=forms.Textarea(attrs={'placeholder': 'Message'}))

    class Meta:
        model = Contact
        fields = ('name', 'email', 'subject', 'message')
</pre>



<p>For the admin interface, let’s create the class in <code>admin.py</code> file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">class ContactAdmin(admin.ModelAdmin):
    list_display = ('name', 'email', 'subject', 'message')

admin.site.register(Contact, ContactAdmin)
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-162.png" alt="" class="wp-image-1496229" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-162.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-162-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>Be sure to import all the necessary modules. For the <code>view</code> function:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.views.generic import CreateView
from django.contrib.messages.views import SuccessMessageMixin
from .forms import ContactForm
from django.contrib import messages
from django.http import HttpResponseRedirect
from django.urls import reverse_lazy

class ContactView(SuccessMessageMixin, CreateView):
    form_class = ContactForm
    success_url = reverse_lazy('index')
    template_name = 'contact.html'
    success_message = 'Your message was submitted successfully'

    def form_invalid(self, form):
        message.error(self.request, 'An unknown error has occurred!')
        return HttpResponseRedirect('')
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-163.png" alt="" class="wp-image-1496230" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-163.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-163-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>let’s now create the template using the name we specified in the <code>ContactView</code> class.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{% extends 'base.html' %}

{% block content %}

&lt;div class="col-md-8 card mb-4 mt-3">
      &lt;h1 align="center">Contact Form&lt;/h1>
      &lt;hr>
      &lt;p>We want to hear from you. Please fill out this contact form for suggestions.&lt;/p>
      &lt;hr>
      &lt;br>
      &lt;form method="post">
        {% csrf_token %}
        {{ form.as_p }}
        &lt;button type="submit" class="btn btn-primary btn-lg">Submit&lt;/button>
     &lt;/form>
 &lt;/div>
{% endblock %}
</pre>



<p>You are free to use the Django crispy forms as demonstrated in that project. For the endpoint, it will be like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('contact', ContactView.as_view(), name='contact'),</pre>
<p>The post <a href="https://blog.finxter.com/how-i-created-a-simple-contact-page-in-python-django/">How I Created a Simple Contact Page in Python Django</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Django &#8211; How I Added More Views to My Hacker News Clone</title>
		<link>https://blog.finxter.com/how-i-added-more-views-to-the-hacker-news-clone-website/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Wed, 05 Jul 2023 15:17:39 +0000</pubDate>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1479921</guid>

					<description><![CDATA[<p>The beginning of this project tutorial on coding the Hacker News clone saw us create three models and two view functions to be rendered on templates for users to view. The first view function simply displays all the posts in the database while the second displays recent posts. As you can see, the templates contain ... <a title="Django &#8211; How I Added More Views to My Hacker News Clone" class="read-more" href="https://blog.finxter.com/how-i-added-more-views-to-the-hacker-news-clone-website/" aria-label="Read more about Django &#8211; How I Added More Views to My Hacker News Clone">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-added-more-views-to-the-hacker-news-clone-website/">Django &#8211; How I Added More Views to My Hacker News Clone</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The <a rel="noreferrer noopener" href="https://blog.finxter.com/how-i-coded-the-hacker-news-clone-in-django-web-application/" data-type="post" data-id="1460992" target="_blank">beginning of this project tutorial</a> on coding the <a href="https://news.ycombinator.com/" data-type="URL" data-id="https://news.ycombinator.com/" target="_blank" rel="noreferrer noopener">Hacker News</a> clone saw us create three models and two view functions to be rendered on templates for users to view. The first view function simply displays all the posts in the database while the second displays recent posts.</p>



<p>As you can see, the templates contain links to several pages that haven’t yet been created.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="376" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-66.png" alt="" class="wp-image-1479926" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-66.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-66-300x157.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>Let’s see how far we can go about creating all these views. Remember, the purpose of this project is to strengthen your understanding of Python and Django as used in web development.</p>



<h2 class="wp-block-heading">The Past Posts</h2>



<p>The second view function of the previous series shows the most recent posts. What if we want to view past posts? The Hacker News website has a link to see posts submitted 30 minutes ago or less. We want to add that feature to our application.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.utils import timezone
from datetime import datetime, timedelta


def PastPostListView(request):
    time = str((datetime.now(tz=timezone.utc) - timedelta(minutes=30)))
    posts = Post.objects.filter(created_on__lte = time)
    for post in posts:
        post.count_votes()
        post.count_comments()

    context={
        'posts': posts,
    }
    return render(request, 'pastpostlist.html', context)
</pre>



<p>This view function filters the posts posted 30 minutes ago. It does that by first defining the time using the <code>datetime</code> module. The module gets the user’s current time zone, subtract 30 minutes from it using the <code>timedelta</code> type, and passes it to the query function. The function has a <code>created_on__lte</code> parameter.</p>



<p>The <code>created_on</code> is the name of the <code>datetime</code> field in the database (check your <code>models.py</code> file) while <code>__lte</code> here means <a href="https://blog.finxter.com/python-less-than-or-equal-to/" data-type="post" data-id="30938" target="_blank" rel="noreferrer noopener">less than or equal</a>.</p>



<p>Thus, it queries the database and filters it based on posts submitted 30 minutes ago or less.</p>



<p>The URL will be like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('past', PastPostListView, name='past_home'),</pre>



<p>And the template will be the same as the previous two templates.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-67.png" alt="" class="wp-image-1479928" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-67.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-67-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<h2 class="wp-block-heading">Displaying user’s info</h2>



<p>On the Hacker News website, each post comes with the name of the person (creator) who submitted it. Also, a link is attached to the name for others to click to learn more about the creator. So, we have to create the views for such.</p>



<p>What do we expect to see on the user’s info page? Of course, the name of the creator, and a link showing all the posts created by the creator. That means we will create two view functions. One for information about the creator and the other for all the posts created by the creator.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def UserInfoView(request,username):
    user = User.objects.get(username=username)
    context = {
        'user': user,
    }
    return render(request, 'user_info.html', context)
</pre>



<p>Here, we call the <code>User</code> class to retrieve information about a particular user and pass it to the <code>render()</code> function which will then be displayed in the template. Since a username is passed as a parameter to the function, the route will also include the username as we can see below:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('user/&lt;username>', UserInfoView, name='user_info'),</pre>



<p>And the template will be like this:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{% extends 'base.html' %}
{% block content %}

&lt;div class="topnav">
  &lt;a class="active" href="{% url 'home'%}">Hacker News&lt;/a>
  &lt;a href="{% url 'new_home'%}">New&lt;/a>
  &lt;a href="{% url 'past_home'%}">Past&lt;/a>
  &lt;a href="{% url 'submit'%}">Submit&lt;/a>

  {% if request.user.is_authenticated %}
    &lt;div class="topnav-right">
      &lt;a href="{% url 'signout' %}">Sign Out &lt;/a>
    &lt;/div>
  {% else %}

&lt;div class="topnav-right">
      &lt;a href="{% url 'signin' %}">Sign In &lt;/a>
    &lt;/div>
  {% endif %}
&lt;/div>

&lt;div class="w3-panel w3-light-grey w3-leftbar w3-border-grey">
&lt;p>&lt;strong>User: &lt;/strong>{{user.username}}&lt;/p>
&lt;p>&lt;strong>Created: &lt;/strong>{{user.date_joined}}&lt;/p>
&lt;/div>

&lt;a href="{% url 'user_posts' user.username %}">Submissions&lt;/a>
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="720" height="405" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-68.png" alt="" class="wp-image-1479929" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-68.png 720w, https://blog.finxter.com/wp-content/uploads/2023/07/image-68-300x169.png 300w" sizes="auto, (max-width: 720px) 100vw, 720px" /></figure>
</div>


<p>Once an individual is logged in, he can see information about the creator. Notice that the user info also shows the date the creator joined our Hacker News clone website. </p>



<p>Now, to see all the posts by a particular creator, there is also a link attached to ‘Submissions.’  This is the second view function we will now create.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">def UserSubmissions(request,username):
    user = User.objects.get(username=username)
    posts = Post.objects.filter(creator = user)
    for post in posts:
        post.count_votes()
        post.count_comments()
    return render(request, 'user_posts.html', {'posts': posts})
</pre>



<p>We call two model Classes in this view function. The first was used to get a particular user (creator) using the username parameter passed to the function, and passes it to the <code>Post</code> class. The second filters all posts based on a particular creator it received from the <code>User</code> class.</p>



<p>As usual, the votes and comments fields for each post have to be populated with their respective number by calling the methods.</p>



<p>The URL routes will be:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">path('posts/&lt;username>',UserSubmissions, name='user_posts'),</pre>



<p>Did you see how the route corresponds to the link attached to ‘Submission’ in the template above? By using the name specified in the URL route, we are referring to this view function. But that is not all. Remember that in the previous view function, the user variable was passed in the context dictionary.</p>



<p>It encompasses every information about the user. Therefore to get the name of the user that will be passed as a parameter to this second view function, <code>user.username</code> has to be included in the link. Once the name is passed to this view function, every post submitted by the person bearing that name will be displayed.</p>



<p>The template for this view function will be:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{% extends 'base.html' %}
{% block content %}

&lt;div class="topnav">
  &lt;a class="active" href="{% url 'home'%}">Hacker News&lt;/a>
  &lt;a href="{% url 'new_home'%}">New&lt;/a>
  &lt;a href="{% url 'past_home'%}">Past&lt;/a>
  &lt;a href="{% url 'submit'%}">Submit&lt;/a>

  {% if request.user.is_authenticated %}
    &lt;div class="topnav-right">
      &lt;a href="{% url 'signout' %}">Sign Out &lt;/a>
    &lt;/div>
  {% else %}
    &lt;div class="topnav-right">
      &lt;a href="{% url 'signin' %}">Sign In &lt;/a>
    &lt;/div>
  {% endif %}
&lt;/div>
&lt;ol>
{% for post in posts %}
  &lt;div class="w3-panel w3-light-grey w3-leftbar w3-border-grey">
  &lt;li>&lt;p>&lt;a href = "{{ post.url }}">{{ post.title }}&lt;/a>&lt;/p>
  &lt;p>{{ post.votes }} | Created {{ post.created_on }}| &lt;a href = "{% url 'user_info' post.creator.username %}">{{ post.creator.username }}&lt;/a> | &lt;a href="{% url 'post' post.id %}"> {{ post.comments }} Comments&lt;/a>&lt;/p>&lt;/li>
&lt;/div>
{% endfor %}
&lt;/ol>
{% endblock %}
</pre>



<p>All the templates we have created so far may appear to look similar but they are not. This one displays every field we created in the post model based on a given creator. Again, using Django template engine in the <code>{% … %}</code> and <code>{{ … }}</code> blocks simplifies everything for us.</p>



<h2 class="wp-block-heading">Conclusion</h2>



<p>So far, we have created five views for the Hacker News clone Django website. Make sure you import the corresponding modules and functions at the top of the <code>urls.py</code> and <code>views.py</code> files. You can always check the <a href="https://github.com/Jonaben1/django_hacker_news_clone" data-type="URL" data-id="https://github.com/Jonaben1/django_hacker_news_clone" target="_blank" rel="noreferrer noopener">full code</a> on GitHub.</p>



<p>Take your time to go through what we have done. if certain things are not clear, you can check the documentation. When we are done coding this application, we will test everything – not in the <code>test.py</code> file – but by populating our database using information from the Hacker News website.</p>



<p>Hopefully, it will help clarify some points. See you in the next series.</p>



<p class="has-base-2-background-color has-background"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Recommended</strong>: <a href="https://blog.finxter.com/how-i-coded-the-hacker-news-clone-in-django-web-application/" data-type="post" data-id="1460992" target="_blank" rel="noreferrer noopener">How I Coded a Hacker News Clone in Django</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-added-more-views-to-the-hacker-news-clone-website/">Django &#8211; How I Added More Views to My Hacker News Clone</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How I Created a Contact Form in a Real Estate Application</title>
		<link>https://blog.finxter.com/how-i-created-a-contact-form-in-a-real-estate-application/</link>
		
		<dc:creator><![CDATA[Jonathan Okah]]></dc:creator>
		<pubDate>Wed, 05 Jul 2023 15:06:54 +0000</pubDate>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web Development]]></category>
		<guid isPermaLink="false">https://blog.finxter.com/?p=1479909</guid>

					<description><![CDATA[<p>The real estate application is already designed and is running on the local server. There are many things we can do to make this application a sophisticated one. However, only two are within the scope of this project. We want to add a contact form so that anyone who needs more information about properties listed ... <a title="How I Created a Contact Form in a Real Estate Application" class="read-more" href="https://blog.finxter.com/how-i-created-a-contact-form-in-a-real-estate-application/" aria-label="Read more about How I Created a Contact Form in a Real Estate Application">Read more</a></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-a-contact-form-in-a-real-estate-application/">How I Created a Contact Form in a Real Estate Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>The <a href="https://blog.finxter.com/how-i-built-a-real-estate-application-using-the-django-web-framework/" data-type="post" data-id="1455098" target="_blank" rel="noreferrer noopener">real estate application</a> is already designed and is running on the local server. There are many things we can do to make this application a sophisticated one. However, only two are within the scope of this project. We want to add a contact form so that anyone who needs more information about properties listed in the app can easily contact us.</p>



<p>At the same time, we can’t just let “strangers” contact us. Interested individuals must be duly registered on our platform. Thus, in upcoming project tutorial, we will add a user <a href="https://blog.finxter.com/how-i-added-a-user-authentication-to-my-django-real-estate-application/" data-type="post" data-id="1479871" target="_blank" rel="noreferrer noopener">authentication feature</a> to this application.</p>



<p>Remember that this is a continuation of the real estate application project. The full code is on <a href="https://github.com/Jonaben1/django_real_estate_app" data-type="URL" data-id="https://github.com/Jonaben1/django_real_estate_app" target="_blank" rel="noreferrer noopener">GitHub</a>.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-61.png" alt="" class="wp-image-1479910" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-61.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-61-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<h2 class="wp-block-heading">Steps in Creating a Contact Form</h2>



<p>We have already created a contact form page when designing a <a href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django/" data-type="post" data-id="1332381" target="_blank" rel="noreferrer noopener">portfolio website</a>. I could have told you guys to go through that tutorial and not spend another time repeating what I have already done previously. However, since this contact page will have a feature not added in that tutorial, I have to design it again.</p>



<p>This will also add to your knowledge as you see various ways to do the same thing using the Django web framework. Here are the steps to get this contact form designed on our application:</p>



<ol class="wp-block-list" type="1">
<li>Create a model for the contact form.</li>



<li>Create a view to handle GET and POST request</li>



<li>Restrict access to the view</li>



<li>Add a template to render the view</li>



<li>Map the view to a URL route</li>
</ol>



<h2 class="wp-block-heading"> The Model</h2>



<p>The model will be used to store the messages in the database. It’s going to contain the name, email, messages and the date the message was received in the database.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from datetime import datetime
class Contact(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
    submitted_on = models.DateTimeField(default=datetime.now)
    message = models.TextField()

    def __str__(self):
        return self.name
</pre>



<p>Next is to apply migrations. Then we proceed to create a contact form in the <code>forms.py</code> file.</p>



<h2 class="wp-block-heading">The Form</h2>



<p>We will subclass the <code>forms.ModelForm</code> class to direct all messages to the database.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = ['name', 'email', 'message']
</pre>



<p>We modify the behavior of the Contact model using the Meta class to display selected fields.</p>



<h2 class="wp-block-heading">The Views</h2>



<p>We will use function-based views instead of the class-based views we used in the first contact form we made.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import ContactForm

@login_required(login_url=‘login’)
def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            # Save the data to the database
            form.save()
            return redirect('home')
    else:
        form = ContactForm()
    return render(request, 'contact.html', {'form': form})
</pre>



<p>In this view, we are using Django’s&nbsp;<code>@login_required</code>&nbsp;decorator to restrict access to the&nbsp;<code>contact</code>&nbsp;view. If a user tries to access this view without being authenticated, they will be redirected to the login page.</p>



<p>We create an instance of the <code>ContactForm</code> class. Once the user enters the required fields defined in the <code>forms.py</code> file and submits the form, it will check whether the form is valid before saving it to the database.</p>



<p>Once the form has been successfully validated and saved, it will redirect the user to the home page. If, though, the request method is GET, it will create an instance of the form and pass it to the <code>render()</code> function to be displayed on a template.</p>



<h2 class="wp-block-heading">The Template</h2>



<p>Next, let’s create a template for our contact form. In the <code>templates/contact.html</code> file, add the following code:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">{% extends 'base.html' %}
{% load tailwind_filters %}
{% block content %}

&lt;div class="col-md-8 card mb-4 mt-3">
      &lt;h1 align="center">Contact Form&lt;/h1>
      &lt;hr>
      &lt;p>Please fill out this form to contact us for more information.&lt;/p>
      &lt;hr>
      &lt;br>
      &lt;form method="post">
        {% csrf_token %}
        {{ form | crispy }}
        &lt;button type="submit" class="btn btn-primary btn-lg">Submit&lt;/button>
     &lt;/form>
 &lt;/div>
{% endblock %}
</pre>



<p>In this template, we are using Django’s built-in forms to create the contact form fields, and crispy tailwind to give it a nice appearance.</p>



<p>The URL will be:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from .views import contact

path('contact', contact, name='contact'),
</pre>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-62.png" alt="" class="wp-image-1479913" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-62.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-62-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<h2 class="wp-block-heading">The Admin</h2>



<p>To see the Contact model in the admin panel, we have to register it in the <code>admin.py</code> file.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">from .models import Contact

admin.site.register(Contact)
</pre>



<p>Login to your admin panel to see the <code>Contact</code> model.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-63.png" alt="" class="wp-image-1479914" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-63.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-63-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<h2 class="wp-block-heading">A little adjustment</h2>



<p>I made some modifications to the real estate application. Check my <a href="https://github.com/Jonaben1/django_real_estate_app" data-type="URL" data-id="https://github.com/Jonaben1/django_real_estate_app" target="_blank" rel="noreferrer noopener">GitHub page</a> to see the full code. Here are some of the adjustments I made:</p>



<ul class="wp-block-list" type="1">
<li>Changing the name of the home page template;</li>



<li>Allowing only the admin to perform CRUD operations by removing the update, edit and delete links;</li>



<li>Restricting access also to the retrieve view;</li>



<li>The link to the contact page now appears on the home page</li>
</ul>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-64.png" alt="" class="wp-image-1479915" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-64.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-64-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>
</div>


<p>Visitors to the website can only see several properties listed but won’t be allowed to access the READ MORE link as well as the contact page without registering on the platform.</p>



<ul class="wp-block-list">
<li>Giving users the option to log out after logging in. The link now appears on the <code>retrieve.html</code> template.</li>
</ul>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="726" height="408" src="https://blog.finxter.com/wp-content/uploads/2023/07/image-65.png" alt="" class="wp-image-1479916" srcset="https://blog.finxter.com/wp-content/uploads/2023/07/image-65.png 726w, https://blog.finxter.com/wp-content/uploads/2023/07/image-65-300x169.png 300w" sizes="auto, (max-width: 726px) 100vw, 726px" /></figure>



<ul class="wp-block-list">
<li>Creating the user authentication feature. <a href="https://blog.finxter.com/how-i-designed-a-personal-portfolio-website-with-django-part-4/" data-type="post" data-id="1461023" target="_blank" rel="noreferrer noopener">Check out this article</a> where I showed how I added the register, login and logout functionality in this application.</li>
</ul>



<h2 class="wp-block-heading">Conclusion</h2>



<p>We come to the end of this tutorial. The application now has a contact page where registered users can reach out to us to know more about properties available for sale.</p>



<p>This is just a simple demonstration of how Django can be used to build applications. Yes, complex applications which are far beyond the scope of this project tutorial.</p>



<p>By taking them one step at a time, you will get to your destination.</p>



<p></p>
<p>The post <a href="https://blog.finxter.com/how-i-created-a-contact-form-in-a-real-estate-application/">How I Created a Contact Form in a Real Estate Application</a> appeared first on <a href="https://blog.finxter.com">Be on the Right Side of Change</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 
Minified using Disk

Served from: blog.finxter.com @ 2026-04-06 22:25:45 by W3 Total Cache
-->