This is a django project with user authentication system for generating sales statistics in an insightful way. The statistics are generated using Pandas
module. We will also see the visual representation of the data which will be powered by Matplotlib
and Seaborn
modules. We will also have a way to compile the stats into a pdf and view it or download it as we like. The authenticated users can also upload data from the client site as form inputs or as a csv file.
-
Setup a virtual environment first using
virtualenv <your environment name>
and then activate it by running<env name>\scripts\activate
on Windows orsource bin/activate
on Mac on Linux. -
Copy the
requirements.txt
in the working directory and runpip install -r requirements.txt
on your terminal to install all the necessary Python modules. -
Run
django-admin startproject core .
to create a Django project in the working directory. The.
creates the project in the root directory of the project. -
In
core/settings.py
file, add the following settings:
STATIC_URL = '/static/' # already existing
STATICFILES_DIRS = [BASE_DIR / 'static'] # new
MEDIA_URL = '/media/' # new
MEDIA_ROOT = BASE_DIR / 'media' # new
-
Update
'DIRS': [BASE_DIR / 'templates'],
for theTEMPLATES
setting. Change the database name if you want, as I changed it asstats_db.sqlite3
. -
Run
python manage.py migrate
to initialize the database and then create a super user by runningpython manage.py createsuperuser
which will prompt you to provide necessary credentials. -
Run
python manage.py runserver
to check whether the environment setup has been successful. If everything works fine, you should see the default django template on the browser, add/admin/
at the end of the URL to visit the admin site.
With this, your environment setup is completed and you are ready to start building all the apps.
-
For almost any Django project, the first thing we do is to create an app and add models in the spawned
models.py
file. In our project, we will first create 5 apps, include them in thesettings.INSTALLED_APPS
option, and then create necessary models in each of those apps. -
Run
python manage.py startapp <App name>
command with"App name" as customers, products, profiles, reports, sales
to create 5 apps. This will create 5 directories in our project with the corresponding app names. -
Write some models in the
models.py
files of each app as in the repository. There are some additional files inprofiles
andsales
app. We have asignals.py
file in theprofiles
app,signals.py and utils.py
in thesales
app. -
The
signals.py
inprofiles
app contains a function which is called when a new user is created. This function creates a profile for the new user automatically. For that, theready
method is overriden in theapps.py
file local to the app. Then the__init__.py
file is modified with adding the linedefault_app_config = 'profiles.apps.ProfilesConfig'
to it. -
The
signals.py
insales
app contains a function which is called when a new sales record is created. This function calculates the total price for all the items selected automatically. For that, theready
method is overriden in theapps.py
file local to the app. Then the__init__.py
file is modified with adding the linedefault_app_config = 'sales.apps.SalesConfig'
to it. -
The
utils.py
file insales
app contains a utility function calledgenerate_code
. This function uses theuuid
module to generate a 12-character transaction ID for our sales records automatically. This is called from the overridensave
method that we wrote in theSale
model.
-
We will create the necessary links in respective
urls.py
scripts and create some function-based and class-based views in respectiveviews.py
scripts. In ourHome View
, let's make a database call using Django ORM methods and pass the retrieved queryset values intoPandas.DataFrame
method. This method converts any list type object in Pandas dataframe. -
Call the
to_html
method on the dataframe object to generate suitable HTML snippet for the dataframe object. This HTML snippet is generated as<table>
HTML element which is then passed as context in the render method to populate the template file and a response is created. This response is then viewed on the client browser.
-
Matplotlib uses different kinds of backends to create images using the data we provide. For our case, we need to display the charts as png images on the frontend; and Anti-Grain Geometry (AGG) backend is the most suitable for this purpose. The bytes stream will be encoded into
base64
object as png format. This can later be decoded asutf-8
. This can then safely displayed on the template and rendered on the webpage as normal png image which can be viewed and downloaded as well. -
For generating graphs and charts using matplotlib and seaborn, and then rendering their bytes stream as png format string, we use two functions called
get_chart
andget_graph
in oursales/utils.py
script. Theget_chart
function is called from thehome_view
using necessary parameters, the function then uses the parameters to generate to graph image in the IO stream. -
The
get_chart
function then calls theget_image
function which uses the IO stream to capture the image as png file and sent to the template to be viewed on the website.
-
Using AJAX calls, send form data to the backend with details to include in a report. Create local
static
directory forreports
app. Then puthome.js
instatic/reports
directory. This file contains javascript to handle sending AJAX requests and receiving JSON reponse and then puting the data from JSON response on the client browser. -
Use the
ReportForm
ModelForm insidereports/forms.py
to take necessary inputs for the report object. Then use the viewcreate_report_view
to store the form data in the database and return JSON response. -
Create
reports/utils.py
file to include additional support functions for the app. In this case, create a functionget_report_image
to create a png file from raw binary data stream and return the image url after storing it.
-
Create templates for report list and individual report items. Place the templates into
templates/reports
directory. Create urls for retrieving these templates using class-based views written insidereports/views.py
file. -
The pdf is generated using
xhtml2pdf
python module. For details, look into thexhtml2pdf Documentation for Django
. By default, the link generated is for direct download. For our applicaiton, we want to view the pdf using url on the browser. Modify theContent-Disposition
key of the response object and get rid of theattachment
option to achieve this.
-
Upload
csv
formatted file with schemaPos,Transaction id,Product,Quantity,Customer,Date
to insert multiple sales records at once. These records then can be used just like the other records inserted manually. Note that, the schema must be identical to the above one. -
Uploading files has been handled using
dropzone.js
, look at thereports/upload.js
file to understand how the uploading works. The database insertion logics are handled in thecsv_upload_view
function ofreports/views.py
script. -
Add 2 urls in the
reports/urls.py
- one for uploader page handled with class-based viewUploadTemplateView
, another for handling the upload url in theupload.js
which calls thecsv_upload_view
and passes all the data.
-
Update the
sales/models.py
file in the CSV model to avoid uploading same file twice. Handle the logic incsv_upload_view
function. -
Remove previous data from the
csvs
,positions
andsales
table to perform migrations, perform the migrations and verify. -
Add alerts to the uploader page on successful upload to notify the user whether file records were stored in the database.
-
The
views
functions for user authentication, i.e., login and logout (we deliberately excluded registration as this is not a public website), are put inside aviews.py
scripts inside the project directory or thecore
directory. Alogin.html
template has been also created insidetemplates/auth
directory. Note that the templates directory here is the root templates directory. -
Decorators and Mixins are included in all views functions and classes that are required to be private only the authenticated users.
-
LOGIN_URL
has been added to thesettings.py
script which is used to redirect any non-authenticated user to the login page. -
Create a profile information page
profiles/main.html
in theprofiles
app templates directory, and this template is rendered using themy_profile_view
view function in theprofiles/views.py
script.
-
Finally, complete the
navbar.html
to create a navigation bar for the website so that you can browse through different pages of the site at ease. Polish up the looks of the navbar using custom css. -
Fix JavaScript mistakes in
home.js
, add few codes to clean up after form submission.
If you find any mistakes, please make a pull request and let us know about the mistake so that we can make amendment to the repository. If you don't understand something, reach out to me using:
Thank you!!!