- Introduction
- User Stories
- UX
- Accessibility
- Database Design
- Features
- Existing Features
- Staff Only Features
- Technologies Used
- External Python Packages Used
- Ecommerce Business Model
- Search Engine Optimization (SEO) & Social Media Marketing
- Testing
- Deployment
- Credits
Table of contents generated with markdown-toc
The project is an E-commerce site for a shop selling specialty coffee and brewing equipment.
Users including guests can browse products and add products to their cart.
Registered users can place orders, save products to a wishlist, save their details for future and see their past orders.
The project was built keeping the Agile management principles in mind, and I utilised many of GitHub's features such as Issue and Projects to implement scrum methodology despite working alone.
I wanted to build a front end for the business owner to manage the shop without entering the Django Admin panel.
Closed Issues on GitHub for the project
I used GitHub issues for the product backlog containing the user stories. Issues were also used for bug reports so I could keep track of tricky bugs over time.
I used the tags feature in GitHub Issues for assigning story points, prioritising features based on the MoSCoW method, and categorising the user stories.
I used the Milestones feature to plan sprints and set deadlines.
User stories were prepared using GitHub Issues and assigned story points based on estimated completion time.
User Stories can been seen below under User Story Testing, and in the GitHub Issues for full details including screenshots, story points and associated sprints.
I used a colour scheme I based on a mockup by Tanim Khan on Dribble that I had previously used and like for a previous project - Plant Cafe.
I used Bootstrap Icons throughout the project for icons such as the cart, edit buttons etc.
I used CSS Variables to use my chosen colour palette and font across the project easily.
:root {
--main-bg-color: rgb(223, 228, 227);
--color-primary: rgb(15, 74, 59);
--color-primary-lighter: rgb(25, 114, 92);
--color-secondary: rgb(255, 208, 138);
--color-tertiary: rgb(218, 217, 205);
--color-white: rgb(255, 255, 255);
--color-black: rgb(0, 0, 0);
--color-off-white: rgb(237, 237, 237);
--font-display-font: 'Rubik', sans-serif;
--bs-breadcrumb-divider: ">";
}
I used the latest version of Bootstrap (5.3), which includes support for CSS Variables. I used this new recommended approach along with my own variables to customise bootstrap elements.
An example of this can be seen on one of the custom classes for button-like links:
.btn-cc {
--bs-btn-color: var(--color-off-white);
--bs-btn-hover-color: var(--color-off-white);
--bs-btn-bg: var(--color-primary);
--bs-btn-hover-bg: var(--color-primary-lighter);
--bs-btn-border-color: var(--color-primary);
--bs-btn-active-border-color: var(--color-primary);
--bs-btn-hover-border-color: var(--color-primary);
}
See: Bootstrap Docs - Root Variables
I used the sans-serif font Rubik from Google Fonts. I like its subtle rounded corners and it makes a nice readable display font for the logo and headings.
For the body text, I let Bootstrap style the font as it used a native font stack for different devices resulting in a nice native looking appearance. See: Bootstrap Docs - Native Font Stack
I drew some wireframes using Balsamiq of the landing page and products page. I knew I had the elements available in Bootstrap to get this layout up and running fast.
I ensured that every element met AAA level in the Web Content Accessibility Guidelines (WCAG).
WebAim contrast check
![](docs/images/webaim-contast-checker.png)Buttons featuring icons have appropriate aria-labels
where necessary, and notification messages have aria-live
tags and are read by screen readers.
I tested navigating the project with VoiceOver on macOS.
I used inline SVGs for icons in the project.
I recently watched Seren Davies' talk Death to Icon Fonts where I learned of the issues that icon fonts can cause for accessibility. I researched the best way to use inline SVG icons, including descriptions where appropriate for screen readers. By using SVGs the icons don't break if a user chooses to use a custom font such as Dyslexie.
SVGs that aren't purely decorative always include an aria-label
for screenreaders, and I tested them using VoiceOver on macOS.
See also:
- Inline SVG vs Icon Fonts - CSS Tricks
- SVG, Icon Fonts, and Accessibility: A Case Study - 24 Accessibility
I used Miro to design the models. I created a Profile model to associate extra information with users not included in the default Django user model.
The landing page features and eye catching hero image and slogan, with a call to action to lead the user to see products for sale.
Underneath is a quick paragraph introducing the business and quick links to the Coffee and Equipment products.
Below that, the three newest products on the shop are highlighted.
The Navbar contains dropdown menus to browse Coffee, Equipment, and Products by Brand.
Guests see links to Register or Login.
Logged in Users will see their username as a dropdown containing:
- My Account
- My Orders
- Wishlist, along with a badge containing the number of items in their wishlist.
- Log Out
In addition to these, staff members have access to:
- Manage Shop
- Manage Products
- Manage Orders
Guests and registered users can add products to their shopping cart, and the total of their cart is displayed clearly in the navbar on medium sized screen sizes and up.
I implemented the cart for guest (non-signed in users) by linking their Session ID to a cart in the database. If they log in, the guest cart is merged into their profile's cart.
I added a way for staff to purge old (not updated in over two weeks) carts from the Database in the Staff Frontend.
On the cart page, users can select if they would like their coffee beans ground.
If you're on the page of a Department, you'll see links to click to get to the subcategories of that department.
A blurb/description accompanies the department or category.
Sorting options are available to sort the list by:
- Newest First
- Name (A-Z)
- Name (Z-A)
- Price (Low to High)
- Price (High to Low)
If there are more than 8 products to display, the list is paginated to 8 per page and links to the different pages shown.
Users can click the product's brand name to find more products from the same brand.
If the product is out of stock, the add to cart button is disabled and replaced with a message.
For Staff Only:
- Staff have access to the Product SKU and an Edit Product button.
Users can either sign up using their Google or directly on the site.
Users signing up with Google don't need to create a password.
After signing up, users need to verify their account by clicking the link in the welcome email.
Handy links to popular Email services are included for quick access.
Logged in users can save products to a wishlist for future reference.
There are four stages to the checkout process, the customer can easily see what stage of the process they are at with the progress bar at the top. I used combination of bootstrap elements to make this semantic progress bar.
- Review Order
- Shipping Address
- Billing Details
- Order Confirmation
If the customer has a saved shipping address, they can populate the form with it by checking the box.
Delivery cost is shown when the user has filled out their address.
The Payment page clearly displays the total to be paid.
All information related to Billing is handled by Stripe. If the user has a default billing address saved in their profile, it will be pre-populated in the Stripe form.
Billing Address or Card details are never saved in the database.
An email is sent to the customer when they make a new order.
I used Stripe's webhooks to only send the email when the payment is successfully completed.
Another email is sent to the customer when their order is dispatched.
The Footer includes:
- A link back to the homepage
- Links to the Contact Us page.
- A link to the Privacy Policy
- A link to the GitHub repository for the project.
I rearranged the sections on mobile to get the layout I wanted.
As the project can collect data from users, I included a Privacy Policy link in the Footer which explains how data may be used. I used GDPR.eu for help writing the policy.
The Privacy Policy is also clearly displayed to users on their first visit in the Cookie Consent popup.
See: Writing a GDPR-compliant privacy notice (template included)
Screenshot of Privacy Policy
![](docs/images/screenshots/screenshot-privacy-policy.png)I implemented a cookie consent banner using handy code from GDPR Compliant Cookie Consent Banner In JavaScript – GlowCookies.
This code is well set up to later implement analytics such as Google Analytics or Meta Pixel.
Screenshot of Cookie Consent banner
![](docs/images/screenshots/screenshot-mobile-cookie-consent.jpeg)Django Messages and Bootstrap's Alerts elements were combined to make elegant dismissible notification messages when the user performs actions.
Screenshot of Notification alert
![](docs/images/screenshots/screenshot-message-notifcations.png)I included metadata for favicons and web app icons
I themed the browser window to match the site with the theme-color <meta>
tag for browsers that support it such as Safari on macOS and Chrome on Android.
I wanted to create a front-end for a business owner to manage the store themselves without needing to code or enter the django-admin panel. I also protected fields in the django-admin panel that shouldn't be manually edited.
Lists of products in the staff dashboard feature lots of extra sorting options to help with managing the shop:
- Hidden First
- On Display First
- Stock (Low to High)
- Stock (High to Low)
- Sales (Low to High)
- Sales (High to Low)
- Oldest First
- Newest First
- Name (A-Z)
- Name (Z-A)
- Price (Low to High)
- Price (High to Low)
Staff members can also easily see stats about the shop such as number of orders, orders yet to dispatch, number of registered users, and more.
Old unused guest carts can be purged from the database here to save on resources.
Screenshot of Shop Management Dashboard
![](docs/images/screenshots/screenshot-manage-shop.png)More Screenshots of Shop Management
Warning before deleting a Department that contains categories and products:
Stats, badge alerting to dispatch new orders:
As a staff member, each product page includes the product's SKU and an edit button. Extra fields are displayed for coffees such as harvest year, weight and processed used.
Screenshot of editing a product as staff member
![](docs/images/screenshots/screenshot-manage-shop-edit-product.png)I used media queries to create a print friendly layout for Orders so they can be printed out as packing slips by the business owner.
A Print Order button is included on the page for staff only.
The Order page also includes a button for staff members to mark an order as dispatched.
Screenshot of Dispatching a Customer Order
![](docs/images/screenshots/screenshot-order-dispatch-button.jpg) ![](docs/images/screenshots/screenshot-order-dispatched.jpg)This updates the order in the database and sends the customer a dispatch notification email.
Custom error pages were added for 403, 404, and 500 errors.
Features I didn't get to implement in this iteration but plan to add in future include:
- Guests should be able to place orders without registering for an account
- A Discount Code system or Option for time-based Sales
- I would like migrate to using Stripe Checkout as some of these features like discount codes come built-in.
- Control over Delivery Options and Costs through the staff dashboard. I didn't want these to be hard coded in but cut this feature due to time constraints.
- Mailchimp could be connected to user profiles to include campaigns such as birthday emails with discounts, or follow up emails on completed orders.
- A "recently viewed" carousel of products to follow the user around the site.
- Sign in with Google, I had trouble getting this working error-free despite using it on previous projects. I will reinstate it in future.
- Add a CAPTCHA or some other form of validation to Contact Us form to prevent abuse.
See also: #wont-fix Issues on GitHub
- Python
- Django used as the Python framework for the site.
- pip for installing Python packages.
- Git for version control.
- Sourcetree for managing the remote repository.
- AWS S3 used for online static file storage.
- PostgreSQL used as the relational database management.
- ElephantSQL used as the Postgres database.
- Heroku used for hosting the deployed back-end site.
- GitHub for storing the repository online during development.
- GitHub Projects was invaluable throughout the project and helped me keep track of things to do and bugs to fix - you can see the project's board here.
- GitPod as a cloud based IDE.
- Balsamiq for wireframing.
- Bootstrap 5 as a front end framework.
- Google Chrome, Mozilla Firefox and Safari for testing on macOS Monterey.
- Microsoft Edge for testing on Windows 11.
- Safari on iOS and iPadOS 15.
- Google Chrome on Android 12.
- Miro for drawing database diagrams.
- Mailchimp for newsletter subscription service.
- Copy.ai for inspiration for some of the slogans and headlines.
- favicon.io to make a favicon for site.
- Device Frames for the device mockups in this README.
- Meta Tags to prepare the Meta tags for social media share previews.
- Markdown Builder by Tim Nelson used to help generate documentation.
This site sells goods to individual customers, and therefore follows a Business to Customer
model.
It is of the simplest B2C forms, as it focuses on individual transactions, and doesn't need anything
such as monthly/annual subscriptions.
It is still in its early development stages, although it already has a newsletter, and links for social media marketing.
Social media can potentially build a community of users around the business, and boost site visitor numbers, especially when using larger platforms such a Facebook.
A newsletter list can be used to send regular messages to site users who opt in, such as what items are on special offer, new items in stock. See Newsletter Marketing below.
I've identified some appropriate keywords to align with my site, that should help users when searching online to find my page easily from a search engine. I made sure to make use of semantic html so these keywords were picked up by search engines.
<meta name="title" content="Coffee Crew">
<meta name="description" content="Dublin based specialty coffee roasters. Fresh coffee and premium brewing kit, fast shipping anywhere in Europe.">
I included Metadata to ensure thumbnails and information is presented correctly when shared on Facebook, Twitter and other Social Media.
I've used XML-Sitemaps to generate a sitemap.xml file. This was generated using my deployed site URL: https://coffee-crew-shop.herokuapp.com
After it finished crawling the entire site, it created a sitemap.xml which I've downloaded and included in the repository.
I've created the robots.txt file at the root-level. Inside, I've included the settings:
User-agent: *
Disallow: /staff/
Disallow: /checkout/
Sitemap: https://coffee-crew-shop.herokuapp.com/sitemap.xml
Further links for future implementation:
- Google search console
- Creating and submitting a sitemap
- Managing your sitemaps and using sitemaps reports
- Testing the robots.txt file
Creating a strong social base (with participation) and linking that to the business site can help drive sales.
I included links in the footer which could be used for potential Facebook, Twitter, Instagram and TikTok presences for the business.
I've created a mockup Facebook business account using the Balsamiq template provided by Code Institute.
Facebook Page Mockup
![](docs/images/facebook-mockup.png)For this business I envision a lot of the social media marketing being very visual, using the current most popular formats like Instagram Reels and TikTok. As these are primarily video based I did not mock any for the purposes of this coding project. However, I used royalty free photos in the project from Unsplash which I felt fit the vibe I would portray on social media, using soft focused earthy tone photos.
I used Mailchimp to set up a newsletter sign-up form on my application, to allow users to supply their email address if they are interested in learning more and to drive repeat business. As the small lot coffees regularly change, I felt a newsletter for coffee enthusiasts keeping them up to date would work well.
I created a template of a potential welcome email and mapped out a potential customer journey in Mailchimp. There's a lot of power in Mailchimp, and campaigns could be set up such as a discount code near a customer's birthday, or integration with webhooks.
I performed extensive manual testing continuously as the project was being developed, and filed bug reports on GitHub as issues were discovered to keep track of bugs. I kept track of how to recreate bugs, expected behaviour, screenshots of the issue and how it was resolved to help myself in future.
I also asked friends to test registering accounts / making purchases / editing their profiles and report back to try and catch any potential issues.
I tested the website on four different operating systems on four different types of hardware and didn't find any rendering bugs or unexpected behaviour between the browsers tested.
Operating System | Chrome | Firefox | Edge | Safari |
---|---|---|---|---|
macOS 13.2 | ✅ | ✅ | ✅ | ✅ |
Windows 11 | ✅ | ✅ | ✅ | N/A |
Android 10 | ✅ | ✅ | ✅ | ✅ |
iOS & iPadOS 16.3 | N/A | N/A | N/A | ✅ |
I tested for responsiveness on many different sized viewports from 320px wide up to Ultrawide resolutions, and using different hardware (Monitors, Laptops, Phones).
I used Polypane during development to test many different viewport sizes at once.
Performance testing was done in Google Chrome on macOS.
Page | Performance | Accessibility | Best Practices | SEO |
---|---|---|---|---|
Landing Page (Mobile) | 96 | 98 | 92 | 100 |
Landing Page (Desktop) | 98 | 100 | 92 | 100 |
Products List (Mobile) | 94 | 98 | 92 | 100 |
Products List (Desktop) | 98 | 99 | 92 | 100 |
Product Detail (Mobile) | 84 | 100 | 92 | 100 |
Product Detail (Desktop) | 97 | 100 | 92 | 100 |
Privacy Policy (Mobile) | 96 | 98 | 92 | 100 |
Privacy Policy (Desktop) | 99 | 98 | 92 | 100 |
Manage Products (Mobile) | 90 | 100 | 83 | 100 |
Manage Products (Desktop) | 98 | 100 | 92 | 100 |
Manage Shop (Mobile) | 99 | 100 | 92 | 95 |
Manage Shop (Desktop) | 94 | 100 | 92 | 100 |
Contact (Mobile) | 96 | 100 | 92 | 100 |
Contact (Desktop) | 98 | 100 | 92 | 100 |
No errors were detected using the WAVE Web Accessibility Evaluation Tool.
Easily login or log out
As a **Site user** I should be able to **Easily login or log out** so that I can **Access my personal account information**- I can log into the site when not logged in
- I can log out of the site from any page
Tested 19/03/2022
Result: ✅ Pass
View a list of products
As a **shopper** I should be able to **view a list of products** so that I can **select some to purchase**- I can browse a list of products on the site
Tested 19/03/2022
Result: ✅ Pass
View individual products
The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.As a Shopper I should be able to view individual products so that I can see the price, description, ratings, and images
- If I click an individual item I can see the price, description, ratings, and images of the item
Tested 19/03/2022
Result: ✅ Pass
Total of basket
The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.As a Shopper I should be able to Easily view the total of my basket at any time so that I can Keep track of what I spend
- I can quickly see the total of the items in my basket
Tested 19/03/2022
Result: ✅ Pass
Easily register for an account
As a **Site User** I should be able to **Easily register for an account** so that I can **Have an account with my details saved to save re-entering them**- I can register for an account with the site
Tested 19/03/2022
Result: ✅ Pass
Personal User Profile
As a **Registered User** I should be able to **have a personalised user profile page** so that I can **View my personal order history and save my payment information**- I can see my order history
- I can save my payment information
- I can update my account information
- I can update my saved addresses
Payment information was offloaded to Stripe not to store any payment info in the database.
Tested 19/03/2022
Result: ✅ Pass
Sort Product List
As a Site User I should be able to Sort the list of available products so that I can Easily identify the best rated, best price and categorically sorted products
- I can sort product list by categories such as price, or name
Tested 19/03/2022
Result: ✅ Pass
View Cart
As a **Shopper** I should be able to **view the items in my cart** so that I can **Identify the total cost of my purchase and all the items I will receive**- I can see all the items in my cart and the total cost
Tested 19/03/2022
Result: ✅ Pass
Adjust Quantity of Items in Cart
As a **Shopper** I should be able to **Adjust the quantity of individual items in my bag** so that I can **Easily make changes to my purchase before checkout**- I can adjust the quantity of items in my cart
- The total price updates
Tested 19/03/2022
Result: ✅ Pass
Order Confirmation via Email
As a **Shopper** I should be able to **Receive an email confirmation after checking out** so that I can **Keep the confirmation of what I've purchased for my records**- If I place an order successfully, I should receive an email confirmation
Tested 19/03/2022
Result: ✅ Pass
Add a product
As a **Store Owner** I should be able to **Add a product** so that I can **sell new items on my store**- I can add new items to the site (without using the Django Admin Panel)
Tested 19/03/2022
Result: ✅ Pass
Add a Product
As a **Store Owner** I should be able to **Add a product** so that I can **sell new items on my store**- I can add new items to the site (without using the Django Admin Panel)
Tested 19/03/2022
Result: ✅ Pass
Edit Products
As a **Store Owner** I should be able to **Edit/Update a product** so that I can **Change product prices, descriptions, images and other product criteria**- I can edit items on the site (without using the Django Admin Panel)
Tested 19/03/2022
Result: ✅ Pass
Delete Products
As a **Store Owner** I should be able to **delete a product** so that I can **remove items no longer on sale**- I can edit items on the site (without using the Django Admin Panel)
Tested 19/03/2022
Result: ✅ Pass
Search Products
As a Shopper I should be able to Search for a product by name or description so that I can Find a specific product I'd like to purchase
- I can search for items available for purchase
Tested 19/03/2022
Result: ✅ Pass
Wishlist / Favourite Items
As a **Shopper** I should be able to **Save products to a wish list** so that I can **find them in future to purchase**- I can click a save/heart icon on an product page
- I can see a list of all the products I have saved
Tested 19/03/2022
Result: ✅ Pass
Select Grind for Coffee purchases
As a **Customer** I should be able to **choose if or how I want my coffee ground** so that I can **receive the right coffee for brewing at home**- I can select a grind type while purchasing coffee
- I can update the grind size in the cart
Tested 19/03/2022
Result: ✅ Pass
Add to Cart as a Guest
As a **Shopper without a registered account** I should be able to **add items to my cart** so that I can **decide if I want to buy them later**- Without being logged in, I can add items to my cart.
- I click 'Add to cart' and the item is added to my cart
- I can see a total of all my items in the nav bar
Tested 19/03/2022
Result: ✅ Pass
Printable Order Docket
As **the business owner** I should be able to **print a print-friendly order docket** so that I can **include it when dispatching orders by post**- If print the order page in the browser, I get a print-friendly page suitable to include for customers
- It should include details about the customer's order and their address
Tested 19/03/2022
Result: ✅ Pass
USTORY
Tested 19/03/2022
Result: ✅ Pass
Complete Order with Payment
As a *Customer I should be able to **pay for my order with a card or Apple/Google Pay** so that I can **receive products from the business.**- If I enter my payment details correctly
- My order is completed
Tested 19/03/2022
Result: ✅ Pass
Email Customer when Order Dispatched
As a **Shopper** I should be able to **Receive an email confirmation when my order is dispatched** so that I can **know when to expect my order*- I should receive an email when the shop has dispatched my order
Tested 19/03/2022
Result: ✅ Pass
Password Recovery
The user story should have a reason to exist: what do I need as the user described in the summary? This part details any detail that could not be passed by the summary.As a Registered User I should be able to Easily recover my password in case I forget it so that I can Regain access to my account
- I can click 'Forgot Password' on the Login Page
- I am able to reset my password and regain access to my account
Tested 19/03/2022
Result: ✅ Pass
Guest cart items move to user cart on login
As a **new registered used** I should be able to **see my cart items in my new profile** so that I can **continue with placing an order**- I have items in my cart as a guest, and I register or log in
- The items should still be in my cart (with any previous ones)
Result: ✅ Pass
- I ended up revising the models more times than I expected during development, despite spending time planning them out in advance. As I built more interoperability between the different Django apps I found more properties and methods that I hadn't initially thought of.
Pages were validating using the W3 HTML Validator, and pages with content that varies based on guest/logged in user/admin status were validated in each state.
W3 HTML Validation
Live links to the validator provided for pages as guests, pages requiring authentication checked by pasting rendered HTML from a logged in user into validator.
Page | URL | Logged In Status | Result |
---|---|---|---|
Landing Page | / | Guest | ✅ No errors or warnings |
Landing Page | / | User | ✅ No errors or warnings |
Shopping Cart | /cart | Guest | ✅ No errors or warnings |
Shopping Cart | /cart | User w/cart items | ❗️ 1 warning due to using different colspans for mobile/desktop, rendered page passes |
Department Page | /shop/d/Equipment/ | Guest | ✅ No errors or warnings |
Products by Department Page | /shop/d/Equipment/ | User | ✅ No errors or warnings |
Products by Category Page | /shop/c/travel | Guest | ✅ No errors or warnings |
Products by Brand Page | /shop/b/kinto | Guest | ✅ No errors or warnings |
Sign Up Page | /accounts/signup/ | Guest | ✅ No errors or warnings |
Login Page | /accounts/login | Guest | ✅ No errors or warnings |
Log Out Page | /accounts/logout | User | ✅ No errors or warnings |
All Products List | / | Guest | ✅ No errors or warnings |
Product Page, sorted | /shop/?sort=date_added | Guest | ✅ No errors or warnings |
Product Detail Page | /item/sunrise | Guest | ✅ No errors or warnings |
My Account Page | /account | Staff | ✅ No errors or warnings |
My Orders Page | /account/orders/ | User | ✅ No errors or warnings |
My Wishlist Page | /wishlist | Staff | ✅ No errors or warnings |
Manage Shop Page | /staff | Staff | ✅ No errors or warnings |
Manage Products Page | /staff/products | Staff | ✅ No errors or warnings |
Manage Orders Page | /staff/orders | Staff | ✅ No errors or warnings |
Privacy Policy Page | /privacy | Guest | ✅ No errors or warnings |
The custom CSS was validated using the W3C CSS Validation Service as CSS level 3 + SVG.
File | Result |
---|---|
base.css |
✅ Pass |
checkout.css |
✅ Pass |
glowCookies.css |
✅ Pass |
All the custom Python files pass PEP8 Validation, which I checked both in the development environment and on CI Python Linter.
# noqa
was used in settings.py
where line breaks in strings would have broken Django functionality.
App | File | Result |
---|---|---|
settings.py |
✅ Pass | |
custom_storages.py |
✅ Pass | |
Cart | adapters.py |
✅ Pass |
Cart | context-processor.py |
✅ Pass |
cart | forms.py |
✅ Pass |
cart | models.py |
✅ Pass |
cart | set_cookie.py |
✅ Pass |
cart | urls.py |
✅ Pass |
cart | views.py |
✅ Pass |
checkout | admin.py |
✅ Pass |
checkout | emails.py |
✅ Pass |
checkout | forms.py |
✅ Pass |
checkout | models.py |
✅ Pass |
checkout | orders_urls.py |
✅ Pass |
checkout | urls.py |
✅ Pass |
checkout | views.py |
✅ Pass |
coffeecrew | urls.py |
✅ Pass |
coffeecrew | StaffMemberRequiredMixin.py |
✅ Pass |
home | forms.py |
✅ Pass |
home | views.py |
✅ Pass |
products | admin.py |
✅ Pass |
products | context_processors.py |
✅ Pass |
products | admin.py |
✅ Pass |
products | views.py |
✅ Pass |
products | models.py |
✅ Pass |
products | signals.py |
✅ Pass |
products | urls.py |
✅ Pass |
profiles | admin.py |
✅ Pass |
profiles | context_processors.py |
✅ Pass |
profiles | forms.py |
✅ Pass |
profiles | models.py |
✅ Pass |
profiles | urls.py |
✅ Pass |
profiles | urls_wish_list.py |
✅ Pass |
profiles | views.py |
✅ Pass |
staff | forms.py |
✅ Pass |
staff | urls.py |
✅ Pass |
staff | views.py |
✅ Pass |
File | Result |
---|---|
checkout_delivery.js |
✅ Pass |
confirm_delete.js |
✅ Pass |
glowCookies.js |
|
print_btn.js |
✅ Pass |
stripe_elements.js |
✅ Pass |
The live deployed application can be found deployed on Heroku.
This project uses ElephantSQL for the PostgreSQL Database.
To obtain your own Postgres Database, sign-up with your GitHub account, then follow these steps:
- Click Create New Instance to start a new database.
- Provide a name (this is commonly the name of the project: coffeecrew).
- Select the Tiny Turtle (Free) plan.
- You can leave the Tags blank.
- Select the Region and Data Center closest to you.
- Once created, click on the new database name, where you can view the database URL and Password.
This project uses AWS to store media and static files online, due to the fact that Heroku doesn't persist this type of data.
Once you've created an AWS account and logged-in, follow these series of steps to get your project connected. Make sure you're on the AWS Management Console page.
Full details of setting up AWS for deployment
-
Search for S3.
-
Create a new bucket, give it a name (matching your Heroku app name), and choose the region closest to you.
-
Uncheck Block all public access, and acknowledge that the bucket will be public (required for it to work on Heroku).
-
From Object Ownership, make sure to have ACLs enabled, and Bucket owner preferred selected.
-
From the Properties tab, turn on static website hosting, and type
index.html
anderror.html
in their respective fields, then click Save. -
From the Permissions tab, paste in the following CORS configuration:
[ { "AllowedHeaders": [ "Authorization" ], "AllowedMethods": [ "GET" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [] } ]
-
Copy your ARN string.
-
From the Bucket Policy tab, select the Policy Generator link, and use the following steps:
-
Policy Type: S3 Bucket Policy
-
Effect: Allow
-
Principal:
*
-
Actions: GetObject
-
Amazon Resource Name (ARN): paste-your-ARN-here
-
Click Add Statement
-
Click Generate Policy
-
Copy the entire Policy, and paste it into the Bucket Policy Editor
{ "Id": "Policy1234567890", "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1234567890", "Action": [ "s3:GetObject" ], "Effect": "Allow", "Resource": "arn:aws:s3:::your-bucket-name/*" "Principal": "*", } ] }
-
Before you click "Save", add
/*
to the end of the Resource key in the Bucket Policy Editor (like above). -
Click Save.
-
-
From the Access Control List (ACL) section, click "Edit" and enable List for Everyone (public access), and accept the warning box.
- If the edit button is disabled, you need to change the Object Ownership section above to ACLs enabled (mentioned above).
Back on the AWS Services Menu, search for and open IAM (Identity and Access Management). Once on the IAM page, follow these steps:
- From User Groups, click Create New Group.
- Suggested Name:
group-coffeecrew
(group + the project name)
- Suggested Name:
- Tags are optional, but you must click it to get to the review policy page.
- From User Groups, select your newly created group, and go to the Permissions tab.
- Open the Add Permissions dropdown, and click Attach Policies.
- Select the policy, then click Add Permissions at the bottom when finished.
- From the JSON tab, select the Import Managed Policy link.
-
Search for S3, select the
AmazonS3FullAccess
policy, and then Import. -
You'll need your ARN from the S3 Bucket copied again, which is pasted into "Resources" key on the Policy.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "s3:*", "Resource": [ "arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*" ] } ] }
-
Click Review Policy.
-
Suggested Name:
policy-coffeecrew
(policy + the project name) -
Provide a description:
- "Access to S3 Bucket for coffeecrew static files."
-
Click Create Policy.
-
- From User Groups, click your "group-coffeecrew".
- Click Attach Policy.
- Search for the policy you've just created ("policy-coffeecrew") and select it, then Attach Policy.
- From User Groups, click Add User.
- Suggested Name:
user-coffeecrew
(user + the project name)
- Suggested Name:
- For "Select AWS Access Type", select Programmatic Access.
- Select the group to add your new user to:
group-coffeecrew
- Tags are optional, but you must click it to get to the review user page.
- Click Create User once done.
- You should see a button to Download .csv, so click it to save a copy on your system.
- IMPORTANT: once you pass this page, you cannot come back to download it again, so do it immediately!
- This contains the user's Access key ID and Secret access key.
AWS_ACCESS_KEY_ID
= Access key IDAWS_SECRET_ACCESS_KEY
= Secret access key
- If Heroku Config Vars has
DISABLE_COLLECTSTATIC
still, this can be removed now, so that AWS will handle the static files. - Back within S3, create a new folder called:
media
. - Select any existing media images for your project to prepare them for being uploaded into the new folder.
- UnderManage Public Permissions, selectGrant public read access to this object(s).
- No further settings are required, so clickUpload.
This project uses Heroku, a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud.
Deployment steps are as follows, after account setup:
- SelectNew in the top-right corner of your Heroku Dashboard, and selectCreate new app from the dropdown menu.
- Your app name must be unique, and then choose a region closest to you (EU or USA), and finally, selectCreate App.
- From the new appSettings, clickReveal Config Vars, and set your environment variables.
Key | Value |
---|---|
AWS_ACCESS_KEY_ID |
insert your own AWS Access Key ID key here |
AWS_SECRET_ACCESS_KEY |
insert your own AWS Secret Access key here |
AWS_S3_REGION_NAME |
region name of the AWS region used (e.g 'eu-central-2') |
AWS_STORAGE_BUCKET_NAME |
name of the bucket in AWS |
DATABASE_URL |
insert your own ElephantSQL database URL here |
DISABLE_COLLECTSTATIC |
1 (this is temporary, and can be removed for the final deployment) |
SECRET_KEY |
insert your Django secret key |
EMAIL_HOST_PASS |
insert your own Gmail API key here |
EMAIL_HOST_USER |
insert your own Gmail email address here |
SECRET_KEY |
this can be any random secret key |
STRIPE_PUBLIC_KEY |
insert your own Stripe Public API key here |
STRIPE_SECRET_KEY |
insert your own Stripe Secret API key here |
STRIPE_WH_SECRET |
insert your own Stripe Webhook API key here |
EMAIL_HOST_USER |
insert your email address for sending emails (I used a Gmail account) |
EMAIL_HOST_PASS |
insert your app password for the email address |
USE_AWS |
True |
HEROKU_HOSTNAME |
insert url of deployed project on Heroku |
Heroku needs two additional files in order to deploy properly.
- requirements.txt
- Procfile
You can install this project's requirements (where applicable) using:
pip3 install -r requirements.txt
If you have your own packages that have been installed, then the requirements file needs updated using:
pip3 freeze --local > requirements.txt
The Procfile can be created with the following command:
echo web: gunicorn app_name.wsgi > Procfile
- replace app_name with the name of your primary Django app name; the folder where settings.py is located
For Heroku deployment, follow these steps to connect your own GitHub repository to the newly created app:
Either:
- Select Automatic Deployment from the Heroku app.
Or:
- In the Terminal/CLI, connect to Heroku using this command:
heroku login -i
- Set the remote for Heroku:
heroku git:remote -a app_name
(replace app_name with your app name) - After performing the standard Git
add
,commit
, andpush
to GitHub, you can now type:git push heroku main
The project should now be connected and deployed to Heroku!
This project can be cloned or forked in order to make a local copy on your own system.
For either method, you will need to install any applicable packages found within the requirements.txt file.
pip3 install -r requirements.txt
.
You will need to create a new file called env.py
at the root-level,
and include the same environment variables listed above from the Heroku deployment steps.
Sample env.py
file:
import os
os.environ.setdefault["AWS_ACCESS_KEY_ID"] = insert your own AWS Access Key ID key here
os.environ.setdefault["AWS_SECRET_ACCESS_KEY"] = insert your own AWS Secret Access key here
os.environ.setdefault["AWS_S3_REGION_NAME"] = insert your AWS bucket region here e.g. 'eu-central-2'
os.environ.setdefault["AWS_STORAGE_BUCKET_NAME"] = insert your own AWS Secret Access key here
os.environ.setdefault["DATABASE_URL"] = insert your own ElephantSQL database URL here
os.environ.setdefault["EMAIL_HOST_PASS"] = insert your own Gmail API key here
os.environ.setdefault["EMAIL_HOST_USER"] = insert your own Gmail email address here
os.environ.setdefault["SECRET_KEY"] = this can be any random secret key
os.environ.setdefault["STRIPE_PUBLIC_KEY"] = insert your own Stripe Public API key here
os.environ.setdefault["STRIPE_SECRET_KEY"] = insert your own Stripe Secret API key here
os.environ.setdefault["STRIPE_WH_SECRET"] = insert your own Stripe Webhook API key here
os.environ.setdefault["STRIPE_RETURN_URL"] = URL for the return address in the Stripe JS
os.environ.setdefault["EMAIL_HOST_USER"] = Email address for email account used to sent emails (I used Gmail)
os.environ.setdefault["EMAIL_HOST_PASS"] = App Password for the email account used
os.environ.setdefault["HEROKU_HOSTNAME"] = insert url of deployed project on Heroku
# local environment only (do not include these in production/deployment!)
os.environ.setdefault("DEBUG", "True")
Once the project is cloned or forked, in order to run it locally, you'll need to follow these steps:
- Start the Django app:
python3 manage.py runserver
- Stop the app once it's loaded:
CTRL+C
or⌘+C
(Mac) - Make any necessary migrations:
python3 manage.py makemigrations
- Migrate the data to the database:
python3 manage.py migrate
- Create a superuser:
python3 manage.py createsuperuser
- Load fixtures (if applicable):
python3 manage.py loaddata file-name.json
(repeat for each file) - Everything should be ready now, so run the Django app again:
python3 manage.py runserver
If you'd like to backup your database models, use the following command for each model you'd like to create a fixture for:
python3 manage.py dumpdata your-model > your-model.json
- repeat this action for each model you wish to backup
You can clone the repository by following these steps:
- Go to the GitHub repository
- Locate the Code button above the list of files and click it
- Select if you prefer to clone using HTTPS, SSH, or GitHub CLI and click the copy button to copy the URL to your clipboard
- Open Git Bash or Terminal
- Change the current working directory to the one where you want the cloned directory
- In your IDE Terminal, type the following command to clone my repository:
git clone https://github.com/davidindub/coffeecrew.git
- Press Enter to create your local clone.
Alternatively, if using Gitpod, you can click below to create your own workspace using this repository.
Please note that in order to directly open the project in Gitpod, you need to have the browser extension installed. A tutorial on how to do that can be found here.
By forking the GitHub Repository, we make a copy of the original repository on our GitHub account to view and/or make changes without affecting the original owner's repository. You can fork this repository by using the following steps:
- Log in to GitHub and locate the GitHub Repository
- At the top of the Repository (not top of page) just above the "Settings" Button on the menu, locate the "Fork" Button.
- Once clicked, you should now have a copy of the original repository in your own GitHub account!
- Pagination links adapted from How to implement a paginator in a Django Class-based ListView compatible with Bootstrap 5
- SKU Generator adapted from SKU Generator
- Set cookie code from Adding Items to Cart without Registering a Account by Dennis Ivy
- Stack Overflow - Django rest auth user_logged_in signal
- Cookie Consent from GDPR Compliant Cookie Consent Banner In JavaScript – GlowCookies
- Bootstrap Icons were used extensively in the project.
- Some product images and descriptions edited from Kinto Europe, Moccamaster, Hario.
- Stock images from Unsplash, thanks to photographers Rodrigo Flores, Nathan Dumlao, Gerson Cifuentes, Etty Fidele, Taisiia Shestopa, Milo Miloezger, Andrew Welch, and Goran Ivos for their beautiful photos.
- Thank you to my CI Mentor Tim Nelson for his help and suggestions.
- Thanks to my partner David for his constant support on my journey to a new career.