ART.IAL is an e-commerce website with artwork gallery where you can not only view but also purchase available artwork.
At the beginning of 2020, my sister started experimenting with paint on canvases that has now gained popularity amongst family, friends, colleagues as well as enquiries from her followers on Instagram. I have therefore decided to commit in creating a website for my sister as a professional platform to sell her artwork. After my graduation, this site will be used as fully functional e-commerce platform.
- UX
- Wireframes
- Information Architecture
- Technologies
- Features
- Changes applied since planning
- Testing
- Deployment
- Credits
- Acknowledgements
This project is my final project for the Code Institute's Full stack development programme. The main goal of this project is to create an e-commerce site using Django framework, which is hosted with AWS as well as implementing a fully functional payment system with Stripe.
- Provide the users with a professional e-commerce online shop to allow secure purchases
- Make profit selling artwork
- Promote the artwork and the brand of the artist
- View new artwork produced by the artist
- Ability to buy artwork online
Applies to all site users:
-
As a user, I am able to access the site on my mobile, tablet, and desktop which is adapted to provide the best experience.
-
As a user, I am able to easily navigate through the website without too much thought and find what I am looking for quickly.
-
As a user, I am able to identify instantly what the site is all about and what it has to offer.
-
As a user, I am able to contact the site owner using a simple form.
-
As a user, I am able to find key information about the artwork I am interested in (such as images, title, dimensions, etc)
-
As a user, I am able to add the artwork to my shopping bag, except if I am a superuser.
-
As a user, I am able to change the content of my shopping bag before continuing to completion (add more or remove the artwork), except if I am a superuser.
-
As a user, I am able to see a full breakdown of the total cost, including the shipping charge before proceeding to payment, except if I am a superuser.
-
As a user, I am able to purchase the artwork using my card in a secure environment, except if I am a superuser.
-
As a user, I am able to receive an email confirmation once I complete the payment, except if I am a superuser.
Applies to new site users:
- As a user, I am able to create an account.
Applies to all returning users:
-
As a user, I am able to login to my existing account and make a quicker purchase.
-
As a user, I am able to view, save and update my personal information.
-
As a user, I am able to view past orders, except if I am a superuser.
-
As a user, I am able to make purchases quicker by having stored information such as address, except if I am a superuser.
-
As a user, I am able to change or reset my password securely.
Applies to a superuser (site owner):
-
As a user, I am able to securely add, edit and delete the information for the specific artwork listed on the website.
-
As a user, I am able to change the tags on the products to specify new items to promote them.
-
As a user, I am able to receive inquiries from the site users after they fill in the contact form straight to my email inbox.
-
As a user, I am able to get an email with the customer orders when the purchases are made.
-
As a user, I am able to manipulate social media icons in the footer of the site (turn social media icons on/off and edit URLs).
-
As a user, I am able to edit content in the
About
section of theHome
page.
- Visually pleasant app design
- Easy site navigation
- Information of the content layed out in a simple and clear way on both mobile and larger screens
- Self-explanatory icons where text is absent
- User information is protected by the site
- User can manipulate elements of the particular page
- Quick app load time
-
Headers, titles
font-family: 'Krona One', sans-serif;
-
Paragraphs, descriptions
font-family: 'Lato', sans-serif;
Firstly, I have created a site map to enable me to clearly plan the site design before I started working on the wireframes. It has also helped me to visualize what apps I will need to create to make this project fit for purpose.
I designed my site moc-ups using balsamiq wireframes. I was focusing on defining the basic layout structure of the app and identifying how displays would change on different screen sizes such as mobile, tablet, and desktop.
You can view all wireframes created for this project in site wireframes folder.
*Please note, as I was developing the project, I have identified some weaknesses in the UX and therefore made the required changes. The deployed site looks somewhat different in comparison to the wireframes. These changes will allow the user to have a better experience and allow easier navigation. Some wireframes that are available to view may not be present in current features. This is due to time constraints and I may consider them for the future, therefore, leaving them. I have also added additional superuser features in the front-end that at the time of the site design didn't realize will be required. Wireframes of these features are not included due to time constraints. The design theme of the features is a close match to the overall site to ensure continuation and flow.
Title | Database Key | Field Type | Validation |
---|---|---|---|
Username | user | OneToOneField 'User' | on_delete=models.CASCADE |
Full Name | default_full_name | CharField | max_length=200, null=True, blank=True |
Phone number | default_phone_number | CharField | max_length=20, null=True, blank=True |
Address Line1 | default_address_line1 | CharField | max_length=80, null=True, blank=True |
Address Line2 | default_address_line2 | CharField | max_length=80, null=True, blank=True |
Town/City | default_town_or_city | CharField | max_length=40, null=True, blank=True |
County | default_county | CountryField | blank_label='County', null=True, blank=True |
Postcode | default_postcode | CharField | max_length=20, null=True, blank=True |
Country | default_country | CountryField | blank_label='Country', null=True, blank=True |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Programmatic Name | name | CharField | max_length=50, null=True, blank=False, unique=True |
Friendly Name | friendly_name | CharField | max_length=50, null=True, blank=False |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Programmatic Name | name | CharField | max_length=50, null=True, blank=False, unique=True |
Friendly Name | friendly_name | CharField | max_length=50, null=True, blank=False |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Programmatic Name | name | CharField | max_length=50, null=True, blank=False |
Friendly Name | friendly_name | CharField | max_length=50, null=True, blank=False |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Name | name | CharField | max_length=254, null=True, blank=False, unique=True |
Image | img | ImageField | null=True, blank=False |
Image Url | image_url | URLField | max_length=1024, null=True, blank=False |
Main image | main_img | BooleanField | default=False |
Room view | room_view | BooleanField | default=False |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Name | name | CharField | max_length=254, null=True, blank=False, unique=True |
Artwork Images Folder | imgs | ManyToManyField' | Image |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Product Category | category | ForeignKey 'Category' | null=True, blank=False, on_delete=models.SET_NULL |
Name | name | CharField | max_length=254, null=True, blank=False, unique=True |
Friendly Name | friendly_name | CharField | max_length=50, null=True |
Collection Name | collection_name | ForeignKey 'Collection' | null=True, blank=False, on_delete=models.SET_NULL |
Description | description | TextField | max_length=800, null=True, blank=False |
Author | author | CharField | max_length=254, null=True, blank=False |
Dimensions | dimensions | CharField | max_length=70, null=True, blank=False |
Price | price | DecimalField | max_digits=6, decimal_places=2, validators=[MinValueValidator(0.01)] |
Images Folder | images_folder | ForeignKey 'ImagesFolder' | null=True, blank=False, on_delete=models.SET_NULL |
Sku | sku | CharField | max_length=254, null=True, blank=False |
Tag | tag | ForeignKey 'Tag' | null=True, blank=True, on_delete=models.SET_NULL |
Is sold | is_sold | BooleanField | default=False |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Order Number | order_number | CharField | max_length=32, null=False, editable=False |
Profile | use_profile | ForeignKey 'Profile' | on_delete=models.SET_NULL, null=True, blank=True, related_name='orders' |
Full Name | full_name | CharField | max_length=50, null=False, blank=False |
EmailField | max_length=254, null=False, blank=False | ||
Phone number | phone_number | CharField | max_length=20, null=False, blank=False |
Address Line1 | address_line1 | CharField | max_length=80, null=False, blank=False |
Address Line2 | address_line2 | CharField | max_length=80, null=False, blank=True |
Town/City | town_or_city | CharField | max_length=40, null=False, blank=False |
County | county | CharField | max_length=80, null=True, blank=True |
Country | country | CountryField | blank_label='Country*', null=False, blank=False |
Postcode | postcode | CharField | max_length=20, null=True, blank=True |
Purchase Date | purchase_date | DateTimeField | auto_now_add=True |
Delivery Cost | delivery_cost | DecimalField | max_digits=6, decimal_places=2, null=False, default=0 |
Order Total | order_total | DecimalField | max_digits=10, decimal_places=2, null=False, default=0 |
Grand Total | grand_total | DecimalField | max_digits=10, decimal_places=2, null=False, default=0 |
Original Bag | original_bag | TextField | null=False, blank=False, default='' |
Stripe Pid | stripe_pid | CharField | max_length=254, null=False, blank=False, default='' |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Order | order | ForeignKey 'Order' | null=False, blank=False, on_delete=models.CASCADE, related_name='lineitems' |
Product | product | ForeignKey 'Product' | null=False, blank=False, on_delete=models.PROTECT |
Quantity | quantity | IntegerField | null=False, blank=False, default=1 |
Line Item Total | line_item_total | DecimalField | max_digits=6, decimal_places=2, null=False, blank=False, editable=False |
Datetime | datetime | CharField | null=True, blank=True, max_length=20 |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Name | name | CharField | max_length=254 |
Description | description | TextField | max_length=800 |
Title | Database Key | Field Type | Validation |
---|---|---|---|
Name | name | TextField | choices=SelectName.choices, max_length=254 |
Icon | icon | CharField | choices=SelectIcon.choices, max_length=50 |
Icon url | url | URLField | max_length=1024, default= '', null=True, blank=True |
- Django
- Django Crispy Forms
- Jinja
- jQuery
- Popper JS
- Bootstrap
- Sweetalert
- Stripe
- Gunicorn
- Psycopg2
- Google fonts
- Font-Awesome
- PIP
- Git
- GitHub
- Heroku
- Visual Studio Code
- Boto 3
- AWS bucket
- Color editor
- Pre-loaders
- Favicons
- Balsamiq
Art-ial website is designed using five applications: Home
, Products
, Profiles
, Bag
, and Checkout
.
- The site has responsive design when viewed on a mobile, tablet, and desktop.
- Easy navigation to external sites, such as social media accounts.
- The user is given feedback when they interact with the website (i.e. when items are added/deleted from the bag, or payment is processed, or they send an enquiry using the form on the
Home
page). - Purchased artwork is immediately allocated sold tag, removed from
Shop
page and is only visible in theGallery
page.
- The users can create an account where they can store personal information such as their address and edit their details.
- Password re-set.
- Existing content about the artwork can be edited, updated, or completely deleted by the Super User in the front end.
- The Super User can add new artwork to
Gallery
andShop
sections of the site. - The Super User can change the content displayed in the
About
section of the site. - The Super User can add/remove/edit additional social media icons displayed in the footer.
- The Super User can see the history of all orders.
- The artwork has allocated tags that are visible to allow the user to identify if it's available for purchase, sold or is newly added.
- Room view image is available for the users to view to enhance the experience.
- All of the artwork listed on this page is available for purchase.
- Room view image is available for the users to enhance the shopping experience.
- Items added to the shopping bag appear in the shopping bag in the navigation part of the header.
- Artwork can be removed from the shopping bag.
- The user can choose to proceed to payment.
- Existing users who have previously made a purchase and are logged in, have their delivery address pre-populated when they proceed to payment.
- Checkout page shows the summary of the order.
- Payment can be made by card using Stripe.
- The Super User can update video banner content and contact info.
- The Super User can switch quick links on and off, and add others.
- FAQ app, which would hold some useful information about shipping, payments, refunds and any other relevant questions answered that many users will have. This would prevent them from filling in a contact form.
- Search function in the gallery page to narrow down and search for all artwork, new, sold or available to purchase artwork.
The reason this feature was not implemented right now as it is not necessary. Art-ial is a small e-commerce site with only a few items available for purchase. Should the site grow, this feature will be reconsidered.
During the development of the site, I have identified a few features that will not be included in the current site or in future. They are:
- The Super User can change the pictures displays in New Artwork and Gallery preview carousels located in the
Home
page.
This section was completely removed from the site as I have identified a better and more UX friendly solution by keeping only video-banner on a home page.
- User can completely delete their account.
Superuser can remove user account in the admin section of the site. This option will not be given to registered users but can be requested by filling in a form.
Testing was done manually throughout the development process. The full rundown of the testing can be found in a separate TESTING.md file.
The Art-ial project was deployed using the VS Code IDE, using Git and GitHub for version control. It is hosted on Heroku and all static files, including images, are hosted in AWS S3 Bucket. Stripe is used for payments and gMail for an email account.
Before deploying the application, install the following:
- Python 3
- PIP
- Git
- Heroku CLI
To deploy Art-ial locally, take the following steps:
-
From the applications repository, click the code button and download the zip file.
Alternatively, you can clone the repository using the following line in your terminal:
git clone https://github.com/neringabickmore/art-ial.git
- Access the folder in your terminal window and install the application's required modules with the following command:
pip3 install -r requirements.txt
- Create
env.py
file to hold your environmental variables in the root level of the application:
import os
os.environ.setdefault('STRIPE_SECRET_KEY', 'YOUR_STRIPE_SECRET_KEY')
os.environ.setdefault('STRIPE_PUBLIC_KEY', 'YOUR_STRIPE_PUBLIC_KEY')
os.environ.setdefault('STRIPE_WH_SECRET', 'YOUR_STRIPE_WH_SECRET')
os.environ.setdefault('DATABASE_URL', 'YOUR_DATABASE_URL')
os.environ.setdefault('SECRET_KEY', 'YOUR_DJANGO_SECRET_KEY')
os.environ.setdefault('DEVELOPMENT', '1')
os.environ.setdefault('AWS_S3_REGION_NAME', 'YOUR_REGION')
os.environ.setdefault('AWS_STORAGE_BUCKET_NAME', 'YOUR_BUCKET_NAME')
os.environ.setdefault('STRIPE_CURRENCY', 'YOUR_CURRENCY')
os.environ.setdefault('LANGUAGE_CODE', 'YOUR_LANGUAGE_CODE')
os.environ.setdefault('TIME_ZONE', 'YOUR_TIMEZONE')
os.environ.setdefault('EMAIL_HOST_USER', 'YOUR_EMAIL_USER')
os.environ.setdefault('EMAIL_HOST_PASSWORD', 'YOUR_EMAIL_PASSWORD')
os.environ.setdefault('EMAIL_HOST', 'smtp.google.com') # if you use gmail
If you plan to make your repository public, ensure you add .env
file to .gitignore
before committing.
- If your IDE terminal, migrate the models to create the database using the following commands:
python manage.py makemigrations
python manage.py migrate
- Create a superuser to access the admin panel using the following command:
python manage.py createsuperuser
Then follow the instructions to create the superuser.
- After you login to the admin panel, you can add data to be displayed in your app for
HOME
andPRODUCT
apps. Refer to database modeling. Alternatively, you can use fixtures, follow below command to load data into the database in the following order:
PRODUCT APP
:
product_categories
, collections
, tags
, images
, images_folder
and only then products
.
HOME APP
:
about_section
, social_media_icons
.
python manage.py loaddata <fixture_name>
- To initiate the application, type the command
python manage.py runserver
in your terminal. The application is now available in your browser at the address:http://localhoset:8000
To deploy the app to Heroku, use the following steps:
- Ensure you have the following dependancies installed in your app, such as PostgressSQL driver for Python, WSHI HTTP Server and dj database url that connects the the app with the database:
pip3 install psycopg2-binary
pip3 install install gunicorn
pip3 install dj_database_url
- If you haven't already, create
requirements.txt
file containing all of the dependancies:
pip3 freeze > requirements.txt
- Create a
Procfile
that contains the following:web: gunicorn art_i_al.wsgi:application
. - Push these newly created files to your repository master.
- Login to Heroku and create a new app.
- In Heroku dashboard of the new app, click deploy, then deployment method and select GitHub to connect your app to your github repository for automatic deployment.
- In Heroku Resources tab, navigate to Add-Ons section and search for Heroku Postgres. I recommend you choose hobby level for this application.
- In settings tab, navigate to Reveal Config Vars and add the following variables:
KEY | VALUE |
---|---|
AWS_ACCESS_KEY_ID | ACCESS_KEY_ID_PROVIDED_BY_AWS |
AWS_S3_REGION_NAME | REGION_PROVIDED_BY_AWS |
AWS_SECRET_ACCESS_KEY | SECRET_ACCESS_KEY_PROVIDED_BY_AWS |
AWS_STORAGE_BUCKET | STORAGE_BUCKET_PROVIDED_BY_AWS |
DATABASE_URL | YOUR_DATABASE_URL |
EMAIL_HOST | smtp.google.com (if using gmail) |
EMAIL_HOST_PASS | YOUR_EMAIL_PASSWORD |
EMAIL_HOST_USER | YOUR_EMAIL_USER |
LANGUAGE_CODE | YOUR_LANGUAGE_CODE |
SECRET_KEY | YOUR_DJANGO_SECRET_KEY |
STRIPE_CURRENCY | YOUR_STRIPE_CURRENCY |
STRIPE_PUBLIC_KEY | YOUR_STRIPE_SECRET_KEY |
STRIPE_SECRET_KEY | YOUR_STRIPE_PUBLIC_KEY |
STRIPE_WH_SECRET | YOUR_STRIPE_WH_SECRET |
TIME_ZONE | YOUR_TIME_ZONE |
USE_AWS | True |
- In settings.py in your IDE, temporarily comment out the database and use below code instead (make sure you do not commit!):
DATABASES = {
'default': dj_database_url.parse('POSTGRESS URL')
}
- In terminal, migrate the models to create the Postgress database using the following commands:
python manage.py makemigrations
python manage.py migrate
- Create a superuser to access the admin panel using the following command:
python manage.py createsuperuser
Then follow the instructions to create the superuser.
- After you login to the admin panel, you can add data to be displayed in your app for
HOME
andPRODUCT
apps. Refer to database modeling. Alternatively, you can use fixtures, follow below command to load data into the database in the following order:
PRODUCT APP
:
product_categories
, collections
, tags
, images
, images_folder
and only then products
.
HOME APP
:
about_section
, social_media_icons
.
python manage.py loaddata <fixture_name>
- Remove the temporary database from settings.py and uncomment the original code, then push the code to origin.
- Back to in Heroku dashboad, deploy the application.
- To view the site, click on View App.
The static and media files are hosted in the AWS S3 Bucket. To host them, you need to create an account in AWS and create your S3 basket with public access. More about setting it up you can read in Amazon S3 documentation and this tutorial.
- I have used the snippet tool for capturing screengrabs which I saved as images.
- I have also used giphy.com to convert MP4 video files to gif files used in Testing.md.
- Image size editor
- Video Compressor
- Videezy for video content on the home page.
- Project was developed by following the Code Institute video course 'Boutique Ado'.
- Stack Overflow for finding solutions or hints on how to solve issues and how to make it work.
- I referred to the Django documentation sources during the development.
- Former CI student's projects.
I'd like to say thank you to everyone who has supported me throughout this project:
- My husband James and my Sister Indre - you were great at supporting me! Thank you ❤
- Fellow CI Students and Tutors - to name a few: Simon, Karol, Michael, Igor, Chris
- Big thank you to everyone who tested my site, including Byllsa, Daisy, Richard and anonymous Ngiap! Thanks for breaking my site and allowing me to fix it! ❤
- My mentor Simen Daehlin - you're the best.