Skip to main content
  1. All Posts/

django-ecommerce-1

eCommerce CSS

THE Pet Store



This is a project for the final milestone project at Code Institute to demonstrate my learning and understanding throughout the course. I chose to develop an ecommerce shopping website as it is a complex and flexible application which challenged my understanding of the technologies involved. Given the sensitivity involved in handling customer details I had to approach development from a security conscious perspective.
Overall I believe I produced an application that is very adaptable and can be repurposed for many ecommerce applications, including subscriptions and transactional services. There are a number of features which I would have liked to include for submission of my milestone project, however, due to time constraints these were not feasible at this point-in-time.

Deployed Application

You can access the application here. If you wish to test account functionality, demo accounts have been provided below. Please note email functionality has not been configured yet, any messages related to emails can be ignored.

Demonstration Data & Accounts

To enable you to test the website functionality, a number of demo accounts, products, and, transactions have been created. You can access this data using the accounts below. Note delete permissions have not been included to preserve test data.

Email
Password
Desription

customer@test.com
test_1234
Customer account with an multiple orders.

staff@test.com
test_1234
Staff account with create and update permissions to the Product model, but no permission to admin area. You will see dropdown menus appear on product listing and product detail page

admin@test.com
test_1234
Admin account with create and update permissions to all custom models, these are accessible in the access admin area.

UX

Given this application is for an ecommerce website, the design is very product and customer centric. It has been designed to enable a customer to add items to their basket, and checkout and pay as seamlessly as possible. All pertinent product information is highlighted upfront, for example, price and rating, to keep customers informed. The menu becomes fixed at the top so the user always knows where they are and can quickly navigate to where they want to go.

Wireframes

Prior to development of the application, I developed a number of wireframes which demonstrate my vision for how the website should look on multiple devices. You can view these wireframes here.

User Stories

Customer

As a customer I want to be able to…

  • Add products to my basket as I browse the website, so that I can continue to browse the website and add more items if I wish.
  • Specify the quantity I would like of each item in my basket, so that I can order multiple items.
  • Search for products, so I can quickly determine if a product is stocked, or find a product I ordered previously.
  • View product ratings and reviews, so that I can see feedback from other users to determine if a product is a good fit for me.
  • Add reviews for products I have purchased, so that I feel that I can contribute to product development and community.
  • Pay for my basket of products using my bank card, so that I do not need to do any unneccessary steps, like bank transfers.
  • View my order history, so that I can see a breakdown of items I’ve previously purchased.
  • View the status of my order(s), so that I have confidence that my order is being processed.
  • update my personal details, including email and password, so that I can self-service as needed.
  • create and pay for an order without any unneccessary steps, so that I can quickly place orders on-the-go.
  • Trust that the company I am transacting with will handle my data securely, so that I do not need to worry about fraud.
  • View detailed product information, so that I can drill into the specific product information I need, for example, product dimensions.

Store Owner

As the store owner, I want the ability to …

  • Add new products and have them automatically display on the website, so that customers can purchase them.
  • Edit product details, for example, price and stock.
  • Remove products from display, so that if I have supply issues I can prevent customers from viewing it.
  • View the status of all customer orders, so that I can efficiently manage the orders.
  • View the most popular products, so that I can ensure I maintain higher stock levels for these items.
  • Link customer orders to the Stripe PaymentIntent dashboard, so that I can verify custom payment details, if I need to.
  • Manage customer reviews, so that I any inappropriate content can be removed if necessary.
  • Update individual items with a customer’s order, so that I can keep customers informed and to manage my workflow.
  • Update customer orders, so that customers are notified in realtime.
  • View all active baskets, so that I can issue targeted discounts to increase basket conversion.

Features

Existing Features

This package enables you to build and deploy a functional ecommerce website, with payment processing through the secure third-party service, Stripe.
The package has been broken into individual apps, the features of which are detailed under each of the headings below.

Custom User Model

To capture additional user information, such as address, I opted to override the default Django user model and create a custom one. This enabled me to store all the necessary user data in one object. It will also make any future user model changes easier to make.
Given the additional data input requirements, I had to specify custom forms in order to capture all the required information. This included overriding Django default forms, for example, the admin forms for adding/modifying user details.

Accounts

This is where all customer information is retained via the custom user model. I also made the decision to use Django-allauth which added the ability to override the username field, using the email address as the login. It also brought with it the ability to verify email addresses and reset passwords.
Within this app I have overriden a number of the default forms provided by allauth to integrate with the customer user model. To produce responsive forms I have used the django-crispy-forms helper function which allows me to create custom form layouts with individual element styling. I have also modified the rendering of the django admin site for the user object, to provide a better structure.
Outlined below are the views that are produced by this app:
a) Signup: a custom form used to create a new user account with the custom user model. The username field is removed, with the email address used in it’s placed. Given this is an ecommerce application, it made more sense to proceed with email only, as a username would not serve any other function than to login.
b) Login: Enables users to login using their email address and password. If any products exist in a user’s basket before they login, these will be merged into any existing basket when the user logs in.
c) Logout: Enables users to logout of their account. The user will be asked to confirm they wish to logout of their account, this prevents accidental logout. When a user logs out any items added to their basket will no longer be visible, however, the basket will be stored in the account and visible upon login.
d) Profile – Personal Details: The user can update their billing address from here. I made the decision to only allow billing address to be changed here for security, so that a user can only use payment cards for one billing address. The billing address is passed through to Stripe upon payment processing. When updating details the user will be provided with feedback flash messages to give a more interaction experience and confirm to the user if an update took place or not.
e) Profile – Change email: A user can have multiple emails if they wish, this functionality is leveraged from django-allauth. The user can log in with all email addresses under their account. I decided to include this functionality to enable users to have one householder account if they wish.
f) Profile – Change password: For security, a user must provide their current password alongside a new password before it will be accepted and updated.

Basket

The Basket app is made up of two models, Basket and BasketItem. The Basket model is used as a container and linked to a user account. BasketItems are then linked to the Basket, via a Many-to-One relationship (i.e. one basket can have many items). The BasketItems record what products a user has added to their basket and the quantity of each (up to a maximum of 5 for each product).
Given this is an ecommerce application, the basket is a critical component of the application’s functionality. It enables anonymous users to create a basket of items, this will be automatically linked to their account/merged with an existing basket upon account login. Users can access their basket at any time to add/update/remove items.
When a basket contains at least one item, the basket icon will display the total item count, to enable the user to keep track of contents without having to click into the basket.
There are a number of components to the basket app, which I have outlined below:
a) Add to Basket: This view is used to add items to the Basket object. If a Basket object does not yet exist it will be created and the product added as a related BasketItem object. Products are automatically added with a quantity of 1, which can be updated in the basket view.
This view will only accept valid product IDs. To prevent accidentally adding the wrong products, the product object ID has been changed to use a UUID.
Feedback flash messages are provided to the user when a product is successfully added, and when adding an item will result in it exceeding the maximum permitted single-item quantity.
b) View/Update Basket: This template makes use of the Django inline formset factory functionality, this enables the updating of multiple database objects at once through a single form. I have setup the form to permit the user to change product quantity and/or remove a product.
Feedback messages are provided to inform the user whether the basket update was successful or not.
c) Middleware: I have created a custom BasketMiddleware class which checks to see if the user has a session variable, basket_id, which is created when a new Basket object is created (step a). I use this to pass-through the user’s Basket object as part of Django’s Request object. I decided to use this method instead of creating multiple session variables because it maintains a single source of truth (the database), and enables me to access the Basket model and associated methods on any view, for example, rendering item count above the basket icon.
d) Basket/BasketItem model methods: Within the Basket model I have created a number of helper functions which enable me to easily check/display values, e.g. item subtotals, total item count, and basket total.
e) Linking a Basket to an account: Through the use of the Django signal, user_logged_in, I have created a function (get_basket) which determines if the user logging in to their account has a basket already stored in the database, if they do this is merged with any items added to their basket prior to login. If no basket existed previously, the basket is then linked to the specific user account and will always be available upon login.
f) Customised Admin Functionality: Given the relationship between Basket and BasketItem, I have amended the admin view so that when accessing a basket, the contents (basketitems) will be displayed with it. The contents can be modified.
g) Create Order: The Basket model also contains a helper method which is used to ‘convert’ a basket into an order. This is only called once payment has been verified. This will be discussed further under the Checkout app.

Checkout

The Checkout app is used to process an order and can only be accessed when a user is logged in with at least one item in their basket. This process captures…