Skip to content

Milestone Project 4: Full Stack Frameworks with Django in Code Institute, Ireland (31 July 2021)

Notifications You must be signed in to change notification settings

Toto-Kotaro-Tanaka/ms4-eagle-golf

Repository files navigation

image

Eagle Golf

This is an e-commerce website for golf products that I create for Milestone Project 4 (Full Stack Frameworks with Django) in Code Institute, Ireland. The use of the website is for educational purposes only, however, all the functionalities work as if it is an actual e-commerce website. It is a mobile responsive website and the link to the website is available HERE.

image

USER STORIES

There are two types of users for the website. One is shoppers whose primary goal is to view golf products and purchase them online. The other one is the shop owner whose primary goal is to sell golf products and run a business. I am a full-stack web developer and create an e-commerce website to meet the primary goals of the users and their stories.

Shopper's User Story

image image

Note:
ID9: Search function works with a keyword only

Owner's User Story

image

Note:
ID5: In a real e-commerce website, products should never be deleted but make them unavailable or something instead. As this is an educational purpose website that CRUD should be implemented, there is a delete products function

UX 5 PLANES

Strategy Plane

To achieve the user's primary goals and stories outlined in the User Stories section, all the functions and features on the tables below are minimum requirements and they are implemented in the website. (On a scale of 1 [least] - 5 [most])

Opportunity Importance Viability / Feasibility
Displaying products by group of categories 5 5
Displaying products by category 5 5
Viewing product details 5 4
Search Function 4 5
Sorting Function 4 5
Modifying products in shopping cart 5 4
Checkout Function 5 4
Secure payment 5 4
Written confirmation after purchase 5 5
Create an account 4 4
Updating personal details 4 5
Resetting password 4 4
Email subscription 3 4
Add, Edit, Remove products (Admin only) 4 4

Below are the additional functions and features that can improve the website, however, these are not mandatory to achieve the current user goals and stories. Some are not implemented due to a lack of my current skills & knowledge and some are due to a lack of time.

Opportunity Importance Viability / Feasibility
Displaying number of product images per product 4 2
(e.g. Image from front, side, back)
Enlarging image when hovering 3 2
Refinements options* 3 2
More detailed categories and advertisement 3 2
Creating an account with social media 3 2
Product comparison** 3 1
Payment in different currencies 2 1

*Example of Refinements options
**Example of Product comparison

Scope Plane

Based on the requirements of achieving user's and owner's goals and stories, below is the list of required pages with the features and functions. CRUD (Create, Read, Update, and Delete) functions are implemented on the website as it is required for admin user's product management.

  • Simple design Home page that the purpose of the website is obvious to anybody and even first-time users know how to navigate the website. Clearly displayed group of categories (e.g. Golf Clubs | Clothing & Shoes) that have categories in it (e.g. Golf Clubs --> Drivers | Irons | Putters)
  • Product pages by the group of categories where users can view all the products belong to the group. Users are navigated to categories in this group from this page
  • Product pages by category where users can view all the products belong to the category
  • Product details page where uses can see all the product details. Users can also select options (e.g. Size, Right / Left) and put the product in the cart
  • Shopping Cart page where users can see all the selected products before purchase. Users can change the quantity of the product or remove it
  • Checkout page where users can provide shipping details and credit card details
  • Checkout success page where users get confirmation of purchase
  • Register page where users can create an account to keep the shipping address saved and to view order histories
  • Login page where users can log in to the page
  • Profile page where users can see the personal details and order histories
  • Logout function that users can safely log out the website and takes users back to the home page
  • Product Management pages (admin only) where admin can add, edit, and delete products
  • 404 & 500 pages where users are taken back to home page safely when they visit a page does not exist or an invalid page

Structure Plane

Front-end

The website consists of below core HTML pages and has some CSS and JavaScript

  • Home (index.html)
    The main page of the website. There is a logo, search function, navigation to Group of Categories & Categories, Register & Login and Shopping Cart pages, a hero image with Shop Now button. There are icons of popular brands that users can click and view the products of the brand. There is a section of "Why Eagle Golf?" which provides a few reasons for buying products with the shop. There is a footer with a form to subscribe to newsletter and some social icons. *The same header and footer are used across all html files

  • Products (products.html, products/<category_name>.html)
    The pages where users can see products by a group of categories & category and have an access to the product details page.

  • Product Details (product/<product_id>.html)
    The pages where users can see product details, with an option to select criteria (e.g. size) and add it in the shopping cart.

  • Shopping Cart (cart.html)
    The page where users can view all the selected products and details. Users can adjust the quantity and there is an option to remove products. There is a button link to a checkout page for the final step of shopping.

  • Checkout (checkout.html)
    The page where users can process the purchase. Strip, which is a secured platform for credit card payment, is used on the website for processing payments.

  • Checkout Success (checkout_success.html)
    The confirmation page where users are lead to when the payment process is completed. Users can see the order number, shipping address, product details. This page is accessible for registered users from Profile.

  • Register (signup.html)
    The page where users can create an account to save their details for next shopping and keep their purchase histories. A form with a built-in function is created with Django Allauth package.

  • Login (login.html)
    The page where users can log in to the website and access to the Profile page to see the personal details and purchase histories. A form with a built-in function is created with Django Allauth package.

  • Profile (profile.html)
    The page where users can see personal details and purchase histories.

  • Add Products (add_products.html)
    The page where only Admin has access and add a new product on the website.

  • Edit Products (edit_products.html)
    The page where only Admin has access and edit products.

  • Page 404 & 500 (404.html, 500.html)
    The error pages that appear when the page is not found or invalid and where users are led to the Home page safely.

  • Base Templates (base.html and base.css)
    The template documents that have core components of html and css and are used among other html files.

  • Admin (/admin)
    The admin panel, which can be created with Django project, where Admin can take control of products and other data.

  • CSS & JavaScript (.css & .js)
    CSS and JavaScript files of those HTML files are created within the same app folder.

Below is the flowchart of the website to show the core relationships between the pages. (Most of the pages are linked to each other subject to permission)

image

Note:
Page 500 is added after the initial planning and it belongs to the same place as Page 404
◦ There is an arrow from Product details to Edit product, however, Edit product cannot be accessed from the Product details page

Back-end

Users have options to purchase products as guest users or account holder users. Guest users cannot save personal details for their next shopping as personal details such as name, email address, shipping address etc belong to their order in the database. Account holder users who create an account with their email address and username, user name (user profile) is linked with their order so that personal details can be retrieved. Each product belongs to a category, a brand and these are identified by id. Each order has a unique order number which is generated when the order is processed and orders have shopper's and product details.
SQLite, which is Django built-in database is used for development mode and Heroku Postgre is used for production mode. AWS (Amazon Web Services) is used to hold all static files and folders for the website for production mode.

Below is the chart of the database to show the data relationships.

image

Skeleton Plane

The website is created as a desktop-first because it is easy to picture the whole image of the website, however, it is a fully mobile responsive website as well so shoppers using a mobile phone have no difficulties looking for products and purchase them. Below are the wireframes of the core pages of the website.

Home (index.html)

Wireframe: Home

Products (products.html)

Wireframe: Products

Product Details (product/product_id.html)

Wireframe: Product Details

Shopping Cart (cart.html)

Wireframe: Shopping Cart

Checkout (checkout.html)

Wireframe: Checkout

Checkout Success (checkout_success.html)

Wireframe: Checkout Success

Note:
No product image and product details on the website

Register (signup.html)

Wireframe: Register

Login (login.html)

Wireframe: Login

Profile (profile.html)

Wireframe: Profile

Product Management (product_management.html)

Wireframe: Product Management

Page 404 (page_404.html)

Wireframe: Page 404

Note:
Page 500: Same as page 404

Surface Plane

Colours

This is an e-commerce website that has a lot of products with images containing different colours, White (#FFFFFF) is used as the main background colour to keep the entire image of the website settled. The shop colour is Hunter Green (#09572A) and this is used for some icons and fonts. Jet (#333333) is used as the main font colour, Golden Yellow (#FFDF00) is used for buttons and alerts to stand them out. Flame (#E84610) is used for other things that need user's attention. These are the base colours and similar colours are used on the different parts and sections on the website.

Note:
Hunter Green (#09572A) is not used for any fonts or icons but used for the colour of toast success

image

Typography

Roboto which is one of the most popular google fonts is used for all the texts because good readability is an important factor for e-commerce websites from the user's point of view. Robot is a default font for Android so many users are very familiar with it as well.

image

WEBSITE DEVELOPMENT PLAN

This is a full-stack website that contains both front-end & back-end, so many Django apps, features and functions, therefore a good website development plan is required to maximise the efficiency of the development. GitHub project planner, which has a Kanban planner, is used for this project. Below is the summary of core tasks* for the website and more detailed tasks are listed on GitHub Projects. This gives not only very clear planning but also making sure nothing is missed during the process.
*Follow the same process as Code Institute Mini Project, Boutique Ado

  1. Planning The Website with UX5 Planes
  2. Project Set-Up (Installing Django, Setting up Project, Testing connection, Creating Django superuser)
  3. Authentication & Authorisation (Installing Allauth, Testing)
  4. The Base Template (Creating base template)
  5. The Home Page (Navigation bar, Header and Footer)
  6. Products Set-Up (Creating Products app, Installing data, Filtering & Searching)
  7. The Shopping Cart (Adding and adjusting products)
  8. Toasts (Real-time notification)
  9. Checkout with Stripe (Function, Form, Testing Stripe)
  10. Profile (Displaying personal details and order history)
  11. Product Admin (CRUD function for products)
  12. Deployment (AWS, Heroku)
  13. Emails (Setting up email functionality)
  14. Code Refactoring (Checking code, Reviewing the design and updating)
  15. Testing (Testing for HTML, CSS, JavaScript, Python, User Stories, Functions and Features)
  16. Final Check Before Submission

Note:
CSS: In previous projects, get confused by Bootstrap CSS classes and my own CSS classes so for this project, two dashes (a kind of BEM methodology) is used on all CSS classes

FEATURES

Existing Features

  • Create with HTML5, CSS3 (with Material Design for Bootstrap), JavaScript, Python (Django Framework), Stripe, AWS and Heroku
  • It consists of 1 product with 5 apps in Django
  • It consists of 1 base html template and 12 main html files. (Excluding sub html files and some allauth html files)
  • Modal for "Delivery Cost" information
  • Toast for user's action
  • All the features planned on Strategy Plane and Scope Plane

Features Left To Implement

  • Displaying number of product images per product: This would probably be possible to implement by using the same principle as Carousel, however, cannot confirm it for sure and do not have time to work on this, decide to leave it out in this project

  • Enlarging image when hovering: Find a few ways of enlarging (zooming) images on hover, however, not sure if these are the same as enlarging images of products that are used in e-commerce websites. Currently, no time to look at the details so decide to leave it out in this project

  • Refinements options: This might be implemented by different combinations of filter, however, currently have no skill to achieve this so decide to leave it out in this project

  • More detailed categories and advertisement: This is to have more detailed categories (e.g. There are only 11 categories but actual e-commerce website, there should be more categories available = more products) and more detailed advertisement such as having different colours, guidance for size etc. Currently have no time to work on this, decide to leave it out in this project

  • Creating an account with social media: Look at a tutorial and not sure if this can be implemented easily. All the testing is done and confirmed all the functions are working, and afraid of breaking something unintentionally by linking social account login, decide to leave this for this project but this is something would like to try with my own project as a challenge

  • Product comparison: This seems to be a very advanced feature and do not even know how to look up for this with my current skill and knowledge so decide to leave it out in this project

  • Payment in different currencies: This might be possible with Stripe rather than Django, but not sure how to achieve this. As this is not an important feature with the current project and do not have time to look at it, decide to leave it out in this project

TECHNOLOGIES USED

  • HTML5 for markup
  • CSS3 for style
  • Material Design for Bootstrap 5 & 4 (an open-source toolkit based on Bootstrap for developing Material Design) for the mainframe of the website
  • JavaScript for interaction
  • Python3 as a backend programming language
  • Django (an open-source web framework) as the main framework of Python
  • SQLite (Django built-in database) as a database in development mode
  • PostgreSQL (Heroku built-in) as a database in production mode
  • Google Fonts for fonts
  • Font Awesome for icons
  • Stripe for credit card payment
  • AWS (Amazon Web Services) for hosting static files and images for the website
  • Gitpod as Integrated Development Environment (IDE)
  • Git for local version control, keeping the files & documents
  • GitHub for online version control and keeping the files & documents
  • Heroku for deploying the website

RESOURCES

General Resources

Tools

TESTING

Testing report is available TESTING.md

PROJECT BARRIERS & SOLUTIONS

Stripe Webhook payment.intent_succeeded

On the development mode, I get payment.intent_succeeded randomly failing although everything else for payment is working. According to debug, it shows local variable ‘intent’ referenced before assignment error so I try to fix the issue by looking at the internet first, but cannot solve it so look at Code Institute Slack. I find a similar post that suggests this can be caused by an error on the form (POST), so check my code on the form to make sure if everything is correct. There are no errors on the form but still get the error so post my query on Code Institute slack and get feedback that also suggests form is usually the issue for local variable ‘intent’ referenced before assignment. I check the form a few more times but cannot find the error so decide to leave it to revisit the issue. When I look at Code Institute slack for something else, I find a post that tells GitPod workspace URL sometimes changes (e.g. eu10 --> eu11) and discover that this is causing the issue for payment.intent_succeeded because the URL I put in Stripe Webhook and my GitPod URL do not match. Also, I find another post that localhost needs to be public (not private) when payments are taken on the website so the issue is solved by having the same URL for Stripe webhook endpoint and GitPod workspace, and having the localhost on the public.

Quantity Buttons for Products

On the Django Mini Project, product id is used to make the quantity buttons disable on JavaScript when the quantity is 1 or max quantity. I follow the same code and implement this on my code for quantity buttons. This works fine when there is only one product on the page, however, when there is the same product with different sizes, it causes an error that the button for the first product works fine but the button for the second product does not. (It does not make disable even quantity is 1 or max quantity) Not sure how to solve the issue so post the query on Code Institute slack but get no response so contact a tutor support. The tutor says using the prodcut id is the issue for this and suggests to use class instead. I try it with class but using class raises another issue that when the button of one of the product is disabled, the other product is also disabled so I decide to keep using product id for this and leave it as it is, because this is a minor issue for the website. *On mobile size, the button is not disabled, even with a single product, as id is being used and that is what I am told by the tutor.

Note:
Using id actually causes html validation errors as duplicate ids. Therefore, class is used for increment and decrement buttons but without having a disable function

First Name and Last Name for Allauth

On the checkout form for registered users, there is a full name field that picks up the first name and last name of the user account. To show the full name from the database, first name and last name fields need to be filled so I try to have these fields available when users create an account. These fields belong to Allauth package, which is pre-built, well secured and has all necessary features, so I copy the file from the site-packages directory and try to modify it but cannot find models.py, forms.py and views.py for it. I search the internet but not sure how to do it so post the query on Code Institute Slack but get no feedback so contact a tutor support. Apparently, modifying Allauth (possibly all built in packages unless you are familiar with them?) is not easy as it looks according to the tutor. I do not want to break some other code by trying to implement this and this is a minor improvement for the webiste, I decide to leave it.

Note:
Create a branch for testing and it gives errors for Stripe webhook as well so take no further action on this

Newsletters App

On the footer of the website, there is a field to subscribe to newsletters. I do not know how to implement this so try to create newsletters app to see if that works. It does not work quite well because the footer is available on all the pages, and also having an app just for subscribe to newsletters seems to be unnecessary so look at Code Institute post to see if anybody implements it. I find a post of someone who sets this up in home app with contexts processor so decide to do it the same. The subscribe function works fine but there are two issues, one same email can be submitted and one that sometimes leads to the server error for some invalid actions (e.g. On the register page, when I put the email address of the user already exists, it gives error 500 instead of showing "User already exists" message) For the first issue, I find a post of someone using .objects.filter().exists() method so I also use it for my function. For the second issue, it looks it is caused by not having () after if subscription_form.is_valid. Code is fixed and everything seems to work fine.

Free Golf Balls Field

As a part of a special offer, users who spend €250 or more will get a box of free golf balls. Initially, I think about having it as a product and add it to the order if the total purchase value is €250 or more. However, this seems to be rather complicated so decided to have a boolean field on the order instead. The field is added after deployment in Heroku. I set up code for this and work fine on development mode but does not work on production mode. First, I check the internet for the solution. I find a post on Stackoverflow and try to solve it by following what it says but I end up messing up my migrations (that I fix it with my mentor because this happens on the same day I have a meeting with him) My migrations on development mode is fixed but still have the issue on the production mode so post it on Code Institue Slack community. Someone points out this is a migrations issue in Heroku, suggests to use heroku run python3 manage.py migrate command but it does not fix the issue. As I cannot solve the issue, I contact tutor support and the tutor says that my postgres in Heroku is corrupted. Therefore, I have to delete it and restore it in Heroku.

VERSION CONTROL

Git as a local repository and GitHub as a remote repository are used for the project, and below is how they are used as the version control for the project.

Setting Up

  1. Create a remote repository in GitHub by clicking "New repository" on the main page

    image

  2. Use Code Institute Template, put the repository name and click Create Repository making sure to select public

    image

  3. Open the repository with Gitpod which is my Integrated Development Environment (IDE). By using Code Institue Template, initialisation including initial commit is done so no need to do git init command when open IDE, or to use git push -u origin main command for my first commit. gitignore file, which is very important for the project including some confidential information, is created with Code Institute template so not necessary to create it, however, it is checked to include files such as pycache, *.sqlite3, env.py etc

    image

Commitments

  • When a section or even a group of work is completed, it is committed in git and pushed into GitHub to make sure to keep the history of the work logged properly and not to lose the work in unexpected situations. Below commands are used for this
* git status | To check the status of new/modified folders, files, and documents
* git add . | To put all new and updated work on the stage in git
  git add <specific file> is used when different types of work are done but do not want to commit everything on the same commitment
* git commit -m "Example commit" | To commit the work on the stage in git before pushing it to GitHub
* git push | To update the repository in GitHub for main / master branch
  git push origin <branch name> is used when pushing git into GitHub for sub-branches

Branches

  • When some testing is needed, create a branch and test it on the branch instead of using the main / master branch. When the testing is successful, then merge the branch into the main / master and when it is not, leave the branch unmerged and keep working on the main / master branch. Below commands are used for this
* git branch <branch name> | To create a new branch
* git checkout <branch name> | To switch branch
* git branch | To check current branch
* git merge <branch name> | To merge sub-branch into main / master, do this on main / master branch

Note:
There are no static files available in the master branch on production mode for some reason so free-golf-balls branch is used for update and the same code is transferred to the master without merging
image

DEPLOYMENT

The website of this project requires back-end technologies such as server, application, and database so the website is deployed in Heroku, which is a cloud platform with a service supporting several programming languages, because GitHub can only host a static website. Heroku Postgres is used for the database. AWS services, which is also a cloud-based platform, is used to store static files and images as Heroku has no files system to store new files.

Below are the processes of deploying the website to Heroku and setting up static files & images in AWS.

HEROKU

  1. Create an app in Heroku. Click New, put App name and select region

    image

    image

  2. Add Heroku Postgres for the database

    image

  3. Install dj_database_url and psycopg2-binary to use Heroku Postgres, and run pip3 freeze > requirements.txt command to add them on requirments.txt

    image

  4. Update settings.py of the product (eagle_golf). Import dj_database_url, comment out sqlite databases and add dj databases variable temporary while the database is transferred to Heroku Postgres

    image

  5. Run python3 manage.py showmigrations command to see the status of migrations (Currently not migrated). Run python3 manage.py migrate command to migrate

    image

  6. Import all products data. Run python3 manage.py loaddata command to load the categories first, brands next and products the last. The order of loading is important as all the products are associated with categories and brands

  7. Create a super user with python3 manage.py createsuperuser command for product admin

  8. Install gunicorn which acts as the webserver, and freeze it into requirements file with pip3 freeze > requirements.txt command

    image

  9. Create a Procfile which specifies the commands that are executed by the app on startup

    image

  10. Temporary disable collectstatic by setting heroku config:set DISABLE_COLLECTSTATIC = 1 and host name of Heroku to allowed hosts in settings.py

  11. Initialise Heroku in git with heroku: git:remote -a ms4-eagle-golf and put git into Heroku with git push heroku master

  12. Set up automatic deployment when git is pushed to GitHub. Go to Deployment on Heroku, search the GitHub repository, connect and click Enable Automatic Deploys

    image

    image

    image

  13. Generate a new secret key, set it up in Heroku and update settings.py. Change the setting of Debug mode that only True in Development mode

    image

    image

  14. Check Activity Feed to see Build in Progress to confirm automatic deployment is working

AWS

  1. Open S3 and create a new bucket, which stores the files, by completing the name and region

    image

  2. Set up basic settings. Enable static website hosting so that it gives a new endpoint for accessing from the internet. Put index.html and error.html as default values

    image

  3. Set up CORS configuration which is the access between Heroku and this S3 Bucket

    image

  4. Set up Bucket Policy. Generate a policy with AWS policy generator. Add /* at the end of Resource to allow access to all resources in the bucket

    image

  5. Create a user to access the bucket. Go to IAM (Identity and Access Management) and create a group for the user to live in. Then, create a policy by importing pre-built policy

    image

    image

    image

    image

    image

  6. Attach the policy to the group

    image

    image

  7. Create a user and add it to the group. When the user is added to the group, it creates csv file containing Access Key ID and Secret access key which are used to authenticate them from Django app. *It is very important to download the file and save it as you cannot download it again

    image

    image

Connecting to DJANGO

  1. Install two new packages, pip3 install boto3, pip3 install django-storages, and run pip3 freeze > requirements.txt command to add them on requirments.txt

    image

  2. Update settings.py to tell Django which bucket it should be communicating with *It is very important to keep AWS access keys secrets as these can be used to store or move data in the bucket and you will be charged by Amazon for it

    image

  3. Add these secret keys on Heroku and set USE_AWS = True

    image

  4. Create custome_storages.py to tell Django to use S3 to store static files and upload images when it is in production

    image

  5. Add AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' to tell Django where the static files come from in production and add some settings for Static and Media files on settings.py

    image

  6. Add all the updates in git, commit it and push it to GitHub. Heroku runs python3 manage.py to collectstatic during the process which also searches through all the apps and project folders looking for static files. Then, it uses S3 domain settings in conjunction with the custom storage classes that tell the location at the URL where the things should be saved when it is in production. This can be confirmed in S3 bucket

    image

  7. Add Cache control on settings.py as static files do not change often and to improve the performance for users

    image

  8. Upload product images via S3. Create a folder, and upload images

    image

    image

  9. Verify superuser's email address on Heroku Postgres. Login admin and check the VERIFIED and PRIMARY boxes

    image

  10. Add Stripe keys to Heroku Config Vars and create a new webhook endpoint

    image

    image

  11. Create Gmail account, add email host pass & user to Heroku Config Vars and add code on settings.py of the product (eagle_golf) image

    image

CREDITS

Code

HTML5

CSS3

JavaScript

Contents

  • All products contents: Online Golf
  • All other contents: Self-written

Media

Logo & Favicon

  • Logo and Favicon created by me using canva

Images

ACKNOWLEDGEMENTS

I would like to thank;

  • My mentor, Spencer Barriball, for going through the project with me and especially solving the database issues with me
  • Chris Zielinski for giving me advice on several queries that I have during the project
  • Code Institute Tutors for giving me a guidance on how to solve some issues

Date: 31 July 2021

About

Milestone Project 4: Full Stack Frameworks with Django in Code Institute, Ireland (31 July 2021)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published