The live link can be found here: Paris Tours
Paris Tours is an e-commerce website that allows users to browse potential tours of Paris and the surrounding area. Users can add tours to their basket and checkout including all e-commerce functionality.
As a standard (not logged-in) user, I would like to:
View the landing page and know that I'm on a website for tourists to Paris who want a guided tour of the city/suburbs
View available tours
Have a unique sign-up option with username and password
Be able to purchase tours without signing up for an account
Subscribe to the newsletter
As a registered (logged-in) user, I would like to:
Have a login option to log in to my previously registered account/profile
Choose from a range of tours and add them to my basket
Create a profile and have my details pre-filled for payment for efficiency
View my order history
As a superuser, I would like to:
Create a company for tourists to come together and explore the wonderful city of Paris and all it has to offer. Users of this site will be able to purchase tours that cater to all tastes. On the database side, CRUD functionality will be implemented so that superusers can create tours (with the ability to both edit and delete them as well) that allow both the business to flourish and visitors to the site to have a steady stream of updated tours at their disposal.
Create a website for people in search of a walking or cycling tour of Paris and the suburbs. A combination of exploration, learning, and exercise.
Link to the Facebook page can be found here
I chose a traditional B2C (Business to Customer) site to execute this project and sell my tours to my target market. This site has a clean and user-friendly interface that allows users to flow from page to page with no obstruction to them making a purchase.
Visitors to my site can purchase up to 10 of each tour (a limit of 10 allows tour guides to control numbers)
The agile development of this project used issues in the project environment on Github
The navigation bar gives you access to the tours page as well as an opportunity to either login with a previously created account or create an account via the sign up option. You can also purchase tours without creating an account and view your basket.
The navigation bar once you are logged in gives you the opportunity to create an account that will store your details for future visits, have an order history with us, as well as log out of your account.
The navigation bar as a superuser gives you the ability to add, edit or delete tours from the database in the Tour Management section.
The sign up page allows you to create an account by providing a username and password for authentication.
As with the sign up page, the login page allows previously registered users to access the extra functionality that having an account provides.
The logout page allows you to confirm if you are sure you would like to logout
The home page welcomes users to the site and gives information on the concept behind the site and encourages you to sign-up to gain access to features where you can create a profile and have a stored order history.
This page presents an ordered list of tours created by the superuser.
The tour detail page presents the selected tour in greater detail so users can gain more information about the tours.
As a superuser, there is functionality to edit and delete tours
As a superuser, this page allows you to add a tour to the database.
As a superuser, this page allows you to add a tour to the database.
This is a detail of the empty basket.
This is a detail of a basket with items in it. The total price is calculated and there is the option to update tours or delete them from the basket, as well as an option to proceed to the checkout. The update button brings you back to the tours page so you can more of the same tour or a different one. The delete button allows you to remove the chosen tour.
The checkout page as a logged out user presents you with a summary of your basket and a form to fill out to pay for your items.
The checkout page as a logged in user allows you to have the payment fields pre-filled on the form.
The order summary page displays a summary of your order once successful payment has been received.
The profile page allows you to view your profile details and order history. It also provides the option to unsubscribe from the newsletter.
The newsletter signup page allows you to subscribe to our newsletter by providing an email address.
The newsletter unsubscribe page allows you to unsubscribe from the newsletter if you wish by providing your email to be removed from our database.
The footer displays social media links and the option to subscribe to the newsletter if you haven't already done so, or unsubscribe if you no longer wish to receive the newsletter.
A review section so users can give feedback on how they felt about the tour. This has the mutual benefit of highlighting to site owners what is working well and what can be improved and to users so that they can have a fine-tuned and fresh range of tours to choose from.
A calendar function so users can reserve a time slot in advance and company owners can know in advancce the numbers they will have for the tour.
Incorporate more of the guide and schedule information from the models on the front-end.
Expand the newsletter subscription so subscribers can receive a monthly newsletter.
Python
JavaScript
CSS
HTML
Django.
Github was used for version control to store commit history.
Heroku was used to deploy our final project.
Balsamiq was used for wireframes.
FontAwesome for social media icons in footer.
Stripe was used for payments.
AWS was used to host media and static files.
Python: Several "line too long" errors were returned when passing through the official Pep8 linter.
These refer to:
AUTH_PASSWORD_VALIDATORS in settings.py
f-strings in webhooks and webhook_handlers
HTML: No errors were returned when passing through the official W3C validator.
CSS: No errors were returned when passing through the official Jigsaw validator.
Base.CSS
Checkout.CSS
I have used Docstrings throughout my code to identify each function and its purpose.
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the Paris Tours title on the navbar | Directed to the home page | Successful |
2 | Click the home button on the navbar | Directed to the home page | Successful |
3 | Click the tours button on the navbar | Directed to the tours page | Successful |
4 | Click the signup button on the navbar | Directed to the signup page | Successful |
5 | Click the login button on the navbar | Directed to the login page | Successful |
6 | Click the my basket button on the navbar | Directed to the my basket page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the Paris Tours title on the navbar | Directed to the home page | Successful |
2 | Click the home button on the navbar | Directed to the home page | Successful |
3 | Click the tours button on the navbar | Directed to the tours page | Successful |
4 | Click the signup button on the navbar | Directed to the signup page | Successful |
5 | Click the login button on the navbar | Directed to the login page | Successful |
6 | Click the my basket button on the navbar | Directed to the my basket page | Successful |
7 | Click the my profile button | Directed to the my profile page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the Paris Tours title on the navbar | Directed to the home page | Successful |
2 | Click the home button on the navbar | Directed to the home page | Successful |
3 | Click the tours button on the navbar | Directed to the tours page | Successful |
4 | Click the signup button on the navbar | Directed to the signup page | Successful |
5 | Click the login button on the navbar | Directed to the login page | Successful |
6 | Click the my basket button on the navbar | Directed to the my basket page | Successful |
7 | Click the my profile button | Directed to the my profile page | Successful |
8 | Click the tour management button | Directed to the tour management page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Select a tour | Directed to the tour detail page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Select a tour | Directed to the tour detail page | Successful |
2 | Click the edit button | Directed to the edit tour page | Successful |
3 | Click the delete button | Deletes a tour | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the add another tour button | Directed to the tour page | Successful |
2 | Click the add to basket button | A tour is added to the basket and confirmation message is displayed | Successful |
3 | Click the quantity arrows | Quantity of chosen tours is increased or decreased | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the add another tour button | Directed to the tour page | Successful |
2 | Click the add to basket button | A tour is added to the basket and confirmation message is displayed | Successful |
3 | Click the quantity arrows | Quantity of chosen tours is increased or decreased | Successful |
4 | Click the edit button | Directed to the edit tour page | Successful |
5 | Click the delete button | Deletes a tour | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the subscribe button without a valid email address | Notified to fill in required field | Successful |
2 | Click the subscribe button with a valid email address | Email address is stored in the database | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the unsubscribe button without a valid email address | Notified to fill in required field | Successful |
2 | Click the unsubscribe button with a valid email address | Email address is removed from the database | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click sign-in link in description | Directed to the sign-in page | Successful |
2 | Click the Sign Up button without required username and password | Notified to fill in required fields | Successful |
3 | Click the Sign Up button with required fields filled | Directed to logged-in homepage | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click sign-up link in description | Directed to the sign-up page | Successful |
2 | Click the Sign In button without required username and password | Notified to fill in required fields | Successful |
3 | Click the Sign In button with required fields filled | Directed to logged-in homepage | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click Sign Out button | Directed to the logged out homepage | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the explore tours button | Directed to the tours page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the cancel update button | Directed to the tours page | Successful |
2 | Click the add tour button without required fields | Notified to fill in required fields | Successful |
3 | Click the add tour button with required fields but no image | Tour is created with default noimage | Successful |
4 | Click the add tour button with required fields and image | Tour is created with chosen image | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the cancel update button | Directed to the tours page | Successful |
2 | Click the edit tour button without required fields | Notified to fill in required fields | Successful |
3 | Click the edit tour button with required fields but no image | Tour is updated with default noimage | Successful |
4 | Click the edit tour button with required fields and image | Tour is updated with chosen image | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the book a tour button | Directed to the tour page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the book a tour button | Directed to the tour page | Successful |
2 | Click the update button | Directed to the tours page to update basket quantity | Successful |
3 | Click the delete button | Deletes tour from basket | Successful |
4 | Click the proceed to checkout button | Directed to the checkout page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the update basket button | Directed to the basket page | Successful |
2 | Click the complete order button without the required fields | Notified to fill in required fields before proceeding | Successful |
3 | Click the complete order button with the required fields and valid card number | Directed to the order summary page and notified that your order was successful | Successful |
4 | Click the create an account link | Directed to the signup page | Successful |
5 | Click the login link | Directed to the login page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the update basket button | Directed to the basket page | Successful |
2 | Click the complete order button without the required fields | Notified to fill in required fields before proceeding | Successful |
3 | Click the complete order button with the required fields and valid card number | Directed to the order summary page and notified that your order was successful | Successful |
4 | Click the create an account link | Directed to the signup page | Successful |
5 | Click the login link | Directed to the login page | Successful |
6 | Pre-filled order form | Order form is pre-filled with profile information | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the return to tours button | Directed to the tours page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the update information button | Directed to the edit profile page | Successful |
2 | Click the subscribe button | Directed to the newsletter signup page | Successful |
3 | Click the unsubscribe button | Directed to the newsletter unsubscribe page | Successful |
4 | Click an order number in order history | Directed to the selected order summary page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click the update information button | Notified that the information has been successfully updated | Successful |
2 | Click the return to profile button | Directed to the profile page | Successful |
Tests | Description | Expected Result | Final Result |
---|---|---|---|
1 | Click Facebook button | Directed to Paris Tours Facebook page in separate tab | Successful |
2 | Click Instagram button | Directed to Instagram homepage in a separate tab | Successful |
3 | Click Twitter button | Directed to Twitter homepage in a separate tab | Successful |
I encountered a minor bug when using Bootstrap for the hamburger icon for smaller screen sizes. The dropdown menu opens perfectly but it won't close again. I believe I have matched my navbar code to the Bootstrap documentation but the menu won't collapse again.
I could not send emails for verification so I added ACCOUNT_EMAIL_VERIFICATION = 'none' in settings.py. If I kept verification on I could still verify credentials in the admin panel.
Favicon images are in AWS but do not appear to be displaying on the live site
I encountered an issue when testing the live site that meant the home page image would not display even though it was in AWS. When inspecting the page, I found that the file path did not include the AWS URL so I inserted it directly into the code.
The live site on Heroku threw a 500 error when I deployed even though it worked on a previous deployment. I cleared the cache, did a hard reload and got the site working.
Create a new app in the Heroku dashboard. Choose a name and location for your app.
Click the resources tab to add the Heroku Postgres database.
Click on the settings tab and reveal config vars. Copy the DATABASE_URL and paste it into the env.py file in your project. Make sure that the env.py file is in the .gitignore file.
Add a SECRET_KEY both to the env.py file and in the config vars on Heroku.
In the Gitpod settings.py file, remove the insecure SECRET_KEY and replace it with the environment variable (SECRET_KEY) that was created.
Replace existing DATABASES section in settings.py file with the DATABASE_URL environment variable that is located in the env.py file.
Ensure that all static and files have been added to the settings.py file in Gitpod.
Add the TEMPLATES_DIR to settings.py file in Gitpod and link it in the TEMPLATES section.
Make sure that the project name for the Heroku app has been added as an allowed host in Gitpod.
Ensure to create a Procfile and add web: gunicorn activities.wsgi to this file
Make sure that the DEBUG flag is set to DEBUG = 'DEVELOPMENT' in os.environ in settings.py file in Gitpod
Add STRIPE_PUBLIC_KEY, STRIPE_SECRET_KEY, STRIPE_WH_SECRET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and USE_AWS to config vars on Heroku
Make sure that all dependencies have been added to the requirements.txt file using the command pip3 freeze > requirements.txt
If deploying through the CLI:
Using the CLI, enter the following commands to deploy to Heroku
Login to Heroku using the command heroku login -i
Enter your email address and password
Find the relevant app using the command heroku apps
Set the Heroku remote using the command heroku git:remote -a
Add, commit and push to Github using the command git add . && git commit -m "Deploy to Heroku via CLI"
Push to both Github and Heroku using the command git push origin main (for Github) and the command git push heroku main (for Heroku)
Bootstrap for some layout and styling features.
TableConvert for the creation of tables in markdown.
Master Code Online for tutorials on how to build a newsletter app.
JShint for JavaScript validation.
Pep8 for Python validation.
W3C for HTML validation.
Pexels for all images used on the site.
A very big thank you to my mentor Daisy McGirr who gave me very helpful feedback and was very encouraging during our mentor sessions.
Also, a big thank you to the Slack community over the course of this entire module.
Stack Overflow for any troubleshooting over the course of this project.