My Indian Recipebook is a web based application that can be used to share recipes for Indian cuisine. Users are able to add their own recipes, edit & delete them, read other user's recipes and add recipes to their favourites.
Please use the below log in details when testing the 'admin' user functionality.
This web based application's primary purpose is to allow the sharing of recipes. The recipes will be available to browse by any visitor to the website. However, additional functionality will be made available for user's that register on the site. A search functionality will provide any visitors the ability to search for recipes by a keyword such as an ingredient or name. Registering on the site will allow users to, once logged in, edit and delete their own recipes. It will also allow them to add other user's recipes to their favourite's list which will then be stored in their profile and be readily available for them to view. A leaderboard on the main page will also allow visitors to see the current most voted for recipes.Please see the wireframes for this project:
Desktop
Mobile
- The audience that this application will be aimed at will be avid home cooks who have a particular interest in Indian Cuisine.
As a user of the website, the following actions and results would need to be achieved:
- As a user, I want to be able to view all of the recipes and to be able to search for recipes containing a specific word.
- As a user, I want to be able to see the top three rated recipes at any given time.
- As a user, I want to be able to see the type of dish, ingredients, method and time to make the recipe.
- As a user, I want to ability to create a profile by entering a username and password.
- As a registered user, I want the ability to log in and log out of my account.
- As a registered user, I want to be able add recipes so that other user can view them.
- As a registered user, I want to be able to see all of my recipes via my Profile and have the ability to edit & delete them if required.
- As a registered user, I want to be able to add other user's recipes to 'My Favourites' and have easy access to them through my Profile.
- As a registered user, I want to be able to vote (upvote or downvote) on other user's recipes.
- As the admin user, I want to be able to remove and edit any recipe regardless of which user added it to the application.
I have kept the design of the webpages simple and easy to navigate.
- All of the headings are the same size, colour & font and the colour scheme is the same throughout.
- Also all of the buttons have the same colour schemes and sizes.
- By using the card class from materialize, whenever the recipes are shown, the stlying and spacing is the same.
- Again with the collapsible class, all of the recipes will be displayed in the same format.
- To ensure that all of the recipes show an image, I have added a generic image to be displayed if an image is not provided by the user. This will allow the design to be the same for each recipe that is added.
Defensive design for this application was built into a lot of the functions as well as the templates. This means that only registered user can access certain parts of the application and edits can only be made by the relevant people.
- An IF statement on the base template means that unless a user is logged in, they only have access to the following pages: Home, Recipes, Log In & Register. They are able to view recipes but cannot vote or add them to favourites.
- The registration form requires a unique username & password to be provided to ensure users cannot duplicate log in details. The password will be hashed before being entered into the users collection for added security.
- The Log In will only be successful if the username & password match those provided in the users collection.
- To ensure only the author of each recipe can edit or delete them, the buttons to do so only appear on their recipes once they are logged in and once they are on their 'My Profile' page.
- To ensure that an admin user has complete control over the content, if they are logged in, they are able to delete and edit any recipe from the 'Recipes' page.
2 Google Fonts were used in this project:
- Delius Unicase - Logo
- Arima Madurai - Main Body text & headings
For this project, there will be 4 collections in the MongoDB database that I have created called 'recipebook'. The tables below show the items in each of the collections.
Key | Value | Data Type |
---|---|---|
_id | Object Id (automatically generated to be unique) | ID |
username | Username decided by user | Varchar/Integer (20) |
password | Password chosen by user that has been hashed | Varchar/Integer (15) |
Key | Value | Data Type |
---|---|---|
_id | Object Id (automatically generated to be unique) | ID |
name | Recipe Name | Text |
ingredients | Recipe ingredients | Text |
method | Method to create dish | Text |
time | Time to create recipe | Time |
meal_type_name | Starter, Main, Side or Dessert | Text |
image | URL for image of finished dish | Text (URL) |
created_by | username of the user who added recipe | Varchar/Integer (20) |
This collection is limited to 4 entries which are: Starter, Meain Course, Side Dish and Dessert. The collection cannot be added to or changed apart from manually through MongoDB.
Key | Value | Data Type |
---|---|---|
_id | Object Id (automatically generated to be unique) | ID |
meal_type_name | Type of dish | Text |
Key | Value | Data Type |
---|---|---|
_id | Object Id (automatically generated to be unique) | ID |
vote | An array which is either upvote or downvote | Text |
recipe_name | Name of dish that has been voted | Text |
added_by | Username of user who is voting | Varchar/Integer (20) |
This collection was originally used however after improvements were made to the code it was no longer required so is no longer referenced in the app.py.
Key | Value | Data Type |
---|---|---|
_id | Object Id (automatically generated to be unique) | Id |
meal_type_name | Type of dish | Text |
name | Recipe Name | Text |
ingredients | Ingredients for selected recipe | Text |
method | Method for selected recipe | Text |
image | URL for image of dish | Text (url) |
added_by | Username of user who added to favourites | Varchar/Integer (20) |
Below is the design of how the collections will work together during the project.
- NAVIGATION
- VIEW RECIPES
- SEARCH RECIPES
- REGISTRATION
- LOGIN
- LOGOUT
- ADD RECIPE
- EDIT RECIPE
- FAVOURITES
- LEADERBOARD
- I would ideally like to connect to a supermarket API which is could then link to the ingredients from each recipe to display the prices of these items and give users the option to purchase them from the recipecard page.
- I would like to add additional functionality to the add & edit recipes form. I would like the user to be able to add the method and ingredients as a separate entry for each item. But I would like them still to be entered as one value in the MongoDB database. This would then allow me to parse the ingredients & method onto separate lines for each entry made by the user.
- I would like to add additional security when deleting recipes such as an extra check to ensure the user wants to delete the item.
- As mentioned in the 'Manual Testing' section, I would like to eliminate the votes collection and instead insert the votes directly into the recipe document in the recipes collection. So, everytime a user either upvotes or downvotes for a recipe, it will add to the count for each in the recipe document. I could then change the leaderboard functionality to pull the recipe with the highest number of upvotes.
- I would also like to improve the 'edit_recipe' functionality to make it easier for the user to edit their recipes. When they click on the 'edit recipe' button they are currently directed to the edit form which is a blank form. I would like the form to already contain all of the details of the recipe that they are trying to edit so that the user does not have to re-enter all of the details. Currently it will take the user a long time to re-type all of the details especially if they only need to edit one details, for example, a quantity for one of the ingredients.
- HTML5
- CSS3
- JavaScript
- Python3
- JQuery
- Materialize - Used to provide page structure, Navbar design and form components. Also used to provide generic styling.
- Font Awesome - Icons for forms and styling.
- Google Fonts - Used to create a look in keeping with the website aim and to create uniform styling throughout.
- Flask Framework
- PyMongo
- Split
- Paginate
- werkzeug.security
- bson
- Counter
- Random
- MongoDB
- Git
- GitHub
- Heroku
- W3C HTML Validator All pages of HTML content have been checked by the HTML validator and have passed.
- W3C CSS Validator
- PEP8 Compliant
Page | Bug Detected | Bug fixed Y/N |
---|---|---|
Main Page (user) | ISSUE FOUND | Y |
Main Page (user logged in) | No issues found | |
Register Page (user) | No issues found | |
Log In Page (user) | No issues found | |
Recipe Page (user) | ISSUE FOUND | Y |
Recipe Page (user logged in) | ISSUE FOUND | Y |
Recipe Page (admin logged in) | ISSUE FOUND | Y |
Individual Recipecard (user) | No issues found | |
Individual Recipecard (user logged in) | No issues found | |
User Profile | No issues found | |
Add New Recipe | No issues found | |
Update Recipe (user's own recipe) | No issues found | |
Update Recipe (admin user) | No issues found | |
Delete Recipe (user's own recipe) | No issues found | |
Delete Recipe (admin user) | No issues found | |
Add to favourites | ISSUE FOUND | Y |
View favourites recipecard | ISSUE FOUND | Y |
If you would like to deploy this project for yourself please see below the steps I followed to deploy and you can do the same:
- Create your new repository (I used GitHub) and then download or clone the following link:
- You will also need to create a cluster in MongoDB and a new collection.
-
This site is currently deployed on Heroku using the master branch on GitHub. You can deploy this project remotely using the following steps:
- Firstly you need to create a requirements.txt file. This is used by Heroku to install all the required dependancies that are needed to run the application. To create the requirements.txt file you will need to enter the following into the terminal:
pip3 freeze --local > requirements.txt You can view the requirements.txt file for this project here to ensure all of the requirements are present in your own file.
- Secondly, Heroku requires a Procfile which tells it what type of application is being deployed and how it should run it. To add the Procfile you will need to enter the below into the terminal:
echo web: python run.py > Procfile
(Please make note that the 'P' in Procfile should be capitalized)
You can view the Procfile for my project here: Procfile
- You will then need to sign up for a free Heroku account or, if you already have one, you will need to sign in. The link to create your account is: https://signup.heroku.com/
- Once signed in to your Heroku account, you will need to create a new app ensuring you select the region closest to your location.
- You then need to choose your deployment method in the Deploy section. If you have created your repository using GitHub, you can connect to the specific repository by searching for the repo-name. If you cannot connect via GitHub, you can connect using Heroku Git (follow the instructions provided on Heroku).
- Once connected, you can 'Enable Automatice Deploys' so if you make any further changes and commits, it will automatically update and deploy a new version of the application.
- In Heroku click on the 'Settings' tab. In the Config Vars section, click on 'Reveal Config Vars' which is used to configure the environmental variables. You will need to set up your env.py file in order to complete this section. Setting up your env.py file can be done as follows:
- Create a new file outside the folder structure called env.py.
- You will need to type 'import os' at the top of this file.
- Then the environment variables need adding as below:
os.environ.setdefault("IP", "0.0.0.0")
os.environ.setdefault("PORT", "5000")
os.environ.setdefault("SECRET_KEY", "insert your secret key here")
os.environ.setdefault("MONGO_URI", "insert your connection string here")
os.environ.setdefault("MONGO_DBNAME", "insert you database name here")
The SECRET_KET can be anything you choose.
The MONGO_URI connection string can be found by doing the following in MongoDB:- Click on the 'Overview' tab
- Click on the 'Connect' option
- Select the 'Connect your application' option
- Select 'Python' as the driver
- You will then be provided with a connection string
- Paste the connection string into MONGO_URI variable
- Ensure you update the sections in capital letters with your own information e.g your password, your cluster name and your collection name: mongodb+srv://myRoot:[email protected]/DATABASE-NAME?retryWrites=true&w=majority".
- Once your env.py file is created, go back to the Config Vars in Heroku and add the IP, PORT, SECRET_KEY, MONGO_URI & MONGO_DBNAME with the correct values as per your env.py file.
- Finally, go back to the 'Deploy' tab on Heroku and in the Manual Deploy section chose the 'main' branch and click 'Deploy Branch'. Once the application has been built, you will receive a message stating 'Your app was successfully deployed' with a link to view the app.
- Firstly you need to create a requirements.txt file. This is used by Heroku to install all the required dependancies that are needed to run the application. To create the requirements.txt file you will need to enter the following into the terminal:
- Navbar & side Navbar taken from Materialize version 1.0.0. This includes the Jquery used to operate the sidenav as well.
- Card class taken from Materialize which includes a floating button.
- Form components HTML & CSS classes taken from Materialize including the Jquery to operate.
- Collapsible component taken from Materialize including the Jquery.
- Pagination implemented using code from https://stackoverflow.com/questions/54053873/implementation-of-pagination-using-flask-paginate-pymongo.
- Google Fonts utilized for all font styles within the project.
- MongoDB Documentation used to help implement the search function and the pull method used in removing an item from favourites.
- Stack Overflow - Implementation of Pagination which was used to implement the pagination on the 'recipes' page.
- Tutor Support assisted with adding the recipe ObjectId into the 'favourites' array and then retrieving the recipe using the ObjectId.
- Code Institute Turtorials were used for reference when creating functions.
- Task Manager Mini Project. Login, Register & Log Out functions taken from this project and just modified to fit in with my milestone project. Other functionality was based around Task Manager function such as the 'add recipe' and 'edit recipe' functions.
- Geeks for Geeks - Python Counter used to help implement the Counter functionality in the voting function.
- Font Awesome used for all icons and symbols.
- Generic Image for recipe found at https://media.istockphoto.com/vectors/fork-knife-icon-vector-id468611140?k=20&m=468611140&s=170667a&w=0&h=vv4BkhlRA35rC-CkIvRBf-r4X9kcFSEQGnzNiJOFH5s=
- Image to show responsive design from http://ami.responsivedesign.is/#