Welcome to my fourth project. This project is a simple restaurant booking system, allow users to book a table for this restaurant. This will use languages such as Django, Python, HTML, CSS and JavaScript.
This project will show the use of CRUD functionality (Create, Read, Update, Delete). The user will be able create, read, update and delete their user profile and table booking.
A live website can be found here.
- 1. UX
- 2. Features
- 3. Technologies Used
- 4. Testing
- 5. Development Cycle
- 6. Deployment
- 7. End Product
- 8. Known Bugs
- 9. Credits
As a big foodie, I have always enjoyed going out to different restaurants to try new cuisines. The simplest way is to book a table at a restaurant. The booking system is best when it's simple to use and asks for the necessary information.
This project will showcase simplicity and ease to booking a table, update a booking, cancel a booking, create a personal profile and update a profile.
The main goal of this project is to allow the user to sign up, sign in/out, create/update a user profile and create/update/delete a table booking in a simple and effective process.
First Time Visitor Goals
- As a first-time visitor, I want to book a table at my chosen date and time.
- As a first-time visitor, I want to view the menu for the restaurant, so that I can decide to book a table or not.
- As a first-time visitor, I want to be able to get the contact details of the restaurant with ease.
Returning Visitor Goals
- As a Returning Visitor, I want to update my booking details.
- As a Returning Visitor, I want to cancel a booking I have already made.
- As a Returning Visitor, I want to edit my profile for any future bookings.
Frequent User Goals
- As a Frequent User, I want to check to see if there are any new food items on the menu.
The system should have a simple user interface, with the navigation to each section clear and concise.
- The menu is clear to read.
- The user interface is easy to navigate.
- The website is responsive on all devices.
- To have the ability to contact the restaurant for any enquiries.
Throughout the project I used the GitHub projects board to log all user stories as my project management tool. This helped me keep focus on the necesarry tasks as I would move them to the "in progress lane" as I'm working on the story. I would then move them to the "done" lane once the story has been completed.
Opportunity/Problem/Feature | Importance | Viability/Feasibility |
---|---|---|
Display a food Menu | 5 | 5 |
Account signup | 5 | 5 |
User profile | 5 | 5 |
Responsive design | 5 | 5 |
Contact form | 4 | 5 |
Ability to create a booking | 5 | 4 |
Ability to update a booking | 5 | 4 |
Ability to cancel a booking | 3 | 4 |
Multiple table occupancies | 4 | 1 |
Avoid double bookings | 4 | 1 |
Total | 45 | 39
As I am unable to include all of the features from the strategy table. I will phase this project in multiple phases. Phase 1 will be what I have identified as a minimum viable product. Please find below the plans I have for each phase.
- Display a food menu
- Allow users to register for an account
- Allow users to create and edit a personal profile
- Responsive design
- Contact form
- Ability to create a booking
- Ability to update a booking
- Ability to cancel a booking
- Multiple table occupancies
- Avoid double bookings
- Contact form model, so messages are saved to the database
- Email confirmation when a message has been received.
- Account email verification
- Replace django-crispy forms with HTML forms for easier control of validation and styling
It is really important to include responsive design in this project as many users are using different devices (mobile, tablet, laptop/PC). This gives the user the best experience on their device.
- Responsive on all device sizes
- Easy navigation through labelled buttons
- Footer at the bottom of the index page that links to the social media website.
- All elements will be consistent including font size, font family, colour scheme.
Final database structure:
class Booking(models.Model):
booking_id = models.UUIDField(
primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(
User, on_delete=models.CASCADE, related_name="user_bookings")
booking_date = models.DateField(auto_now=False)
booking_time = models.TimeField(auto_now=False)
booking_comments = models.TextField(max_length=200, blank=True)
created_on = models.DateTimeField(auto_now_add=True)
guest_count = models.IntegerField()
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-booking_date']
class UserProfile(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
first_name = models.CharField(max_length=150)
last_name = models.CharField(max_length=150)
phone_number = models.CharField(max_length=11)
def __str__(self):
return str(self.user)
From left to right home > navigation bar > menu mobile:
From left to right online bookings > contact form part 1 > contact form part 2 mobile:
From left to right edit profile > manage bookings mobile:
From left to right resgister > navigation bar when user is logged in mobile:
Please find the colours schemes that I used here.
I decided to use Be Vietnam Pro as my font of choice with sans serif as my backup font for browsers that might not support Be Vietnam Pro.
The link to the font can be found here.
-
The navigation bar is placed at the top of all pages. The navigation bar is dynamic in that meaning depending on if the user is logged in or not the options will change.
-
If the user is not logged in the navigation bar will look like this:
-
If the user is logged in the navigation bar will look like this:
-
The footer is placed at the bottom of each page with social media icons. When hovering over them it creates a zoom effect giving the user more of an experience. These icons will open the links in a new tab.
-
The restaurant logo is also placed at the top of all pages. Clicking on it will also direct the user to the home page.
-
Animated background, to give more of a user experience instead of a plain static background.
- A simple signup form that requires the user to enter a unique email address and a password. The password must be entered again for confirmation, this must match the already entered password above.
- A message to prompt the user that if an account is already been created they can click the sign-in hyperlink to be redirected to the sign-in page.
- If the user enters an email address that has already been registered, the user is prompted by an error message.
- If the user enters a password that is not secure, the user will be prompted by a message.
- If the user enters both passwords that do not match, the user is prompted by a message.
- Once the user has successfully signed up, this will automatically log in and direct the user to the create profile page.
- A login form that requires the user to enter their email address and password that they used when signing up to the site.
- A message to prompt the user that if an account has not been created they can click the signup hyperlink to be redirected to the signup page.
- If the user enters in the wrong credentials, a message is displayed to the user.
- When clicking logout from the navigation bar, the user is redirected to a sign-out page to confirm their action.
- A simple but elegant banner to give the user a sense of the restaurant.
- A book now button that directs the user to create a booking page. If the user has not logged in it will prompt the user to register or log in first.
- A short introduction to describe the restaurant.
- Once the user has registered they will be redirected to the create profile page. The page displays a form for the user to enter their first name, last name and telephone number.
- The user can navigate to this page by clicking on the edit profile link in the navigation bar. This page will display the current profile details with a form below for the user to update any details.
- The restaurant opening times are displayed at the top of the page.
- A menu that is displayed in 3 sections by the food category.
- An information section that displays the restaurant telephone number, email address, opening times and address.
- A contact form that requires the user to enter their full name, email address and a message. The form is already pre-filled with the user's full name (if the user is logged in and has created a profile).
- A Google maps iframe of the restaurant location.
- A form that requires the user to enter/select the booking details. Full name and contact telephone number are prefilled if the user has created a profile. The user will then need to select a date, time, number of guests and enter any allergy information if needed.
- The date input field has JavaScript code so the default value is today's date and the user cannot select a date that is previous to today.
- When clicking the make reservation button the booking will then be requested to the restaurant owner for approval.
- As the restaurant is only open from 2 PM, if the user selects a time before that, the form will display an error, prompting the customer to select a later time.
- Displays all user-related bookings in a list view within a card.
- Each card will show a booking reference, booking status, booking date, booking time, guest count. It will also contain a button to change booking details and a cancel booking button.
- This page will display the current booking details with a form below for the user to update any details.
- When the changes are submitted, the booking will be processed as the booking requested status.
- When the user clicks the cancel booking button they will be redirected to a confirmation page.
- HTML5
- The project uses HyperText Markup Language.
- CSS3
- The project uses Cascading Style Sheets.
- JavaScript
- The project uses JavaScript.
- Python
- The project uses Python.
- Boostrap 5
- The project uses Bootstrap 5.
- PostgreSQL
- The project uses PostgreSQL as a database.
- Gitpod
- The project uses Gitpod.
- Chrome
- The project uses Chrome to debug and test the source code using HTML5.
- Balsamiq
- Balsamiq was used to create the wireframes during the design process.
- Google Fonts
- Google fonts were used to import the "Be Vietnam Pro" font into the style.css file which is used on all pages throughout the project.
- GitHub
- GitHub was used to store the project's code after being pushed from Git.
For every element that I added to my HTML, I would add the basic CSS to my stylesheet. I would then use the inspect element to try different styles. Once I've got it to my liking I would try to see if I can implement the styling with bootstrap, if I could not replicate the styling I would copy the CSS from google and paste it into my CSS stylesheet. This allows me to keep track of the code I am using.
I also checked the accessibility of the page using lighthouse.
I used Am I Responsive to make sure that all my pages are responsive to all devices.
I used W3C Markup to check for any errors within the HTML pages.
I had an error on the base.html template:
This was then rectified by adding the lang attribute to the current HTML tag and deleting the other one.
I had an error on the contact.html template:
This was then rectified by removing the width styling of 100% and replacing it with a class="w-100".
I used W3C CSS Validation to check for any errors within my CSS stylesheet.
I had no errors in my CSS file:
I used JS Hint to check for any errors within my JavaScript script tags. JS Hint showed warnings on line 1 which was missing a semicolon, however as this was for the script tag I have ignored it. This piece of JavaScript was along copied and pasted from an external source therefore, I have not made any changes to the code.
I had no errors in my JavaScript files:
I used PEP8 online to check for any errors within my Python files. The validator showed multiple "line too long" errors. This was rectified by adding each statement as a new line.
There were also "line too long" errors within my settings.py file but I have chosen to ignore these as this is a very important file.
I have tested my site on Safari and google chrome on multiple devices.
These include:
- iPhone X
- iPhone XS Max
- iPad Pro
- MacBook Pro
Please find below my testing process for all pages via mobile and web:
All Pages:
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Home page | When clicking the "home" button in the navigation bar, the browser redirects me to the home page. The is active styling will appear as the home button has a red background. | PASS |
Menu page | When clicking the "menu" button in the navigation bar, the browser redirects me to the menu page. The is active styling will appear as the menu button has a red background. | PASS |
Contact page | When clicking the "contact" button in the navigation bar, the browser redirects me to the contact page. The is active styling will appear as the contact button has a red background. | PASS |
Book now page | When clicking the "book now" button in the navigation bar, the browser redirects me to the book now page. The is active styling will appear as the book now button has a red background. | PASS |
Manage booking page | When clicking the "manage bookings" button in the navigation bar, the browser redirects me to the manage booking page. The user will know they are on this page by the heading. | PASS |
Edit profile page | Checked foreground information is not distracted by backgrounds | PASS |
Register page | When clicking the "register" button in the navigation bar, the browser redirects me to the register page. The user will know they are on this page by the heading. | PASS |
Login / Logout page | When clicking the "login" or "logout button in the navigation bar, the browser redirects me to the login or logout page. The user will know they are on this page by the heading. | PASS |
Foreground & background colour | Checked foreground information is not distracted by background animation. | PASS |
Text | Checked that all fonts and colours used are consistent. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
When clicking the Facebook icon, a new tab opens and redirects to the Facebook website. | PASS | |
When clicking the Twitter icon, a new tab opens and redirects to the Twitter website. | PASS | |
When clicking the Instagram icon, a new tab opens and redirects to the Instagram website. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on the page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Book now button | When clicking the book now button on the page, the browser redirects to the booking page. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Book now button | When clicking the book now button on the page, the browser redirects to the booking page. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Contact Form | Checked the form submits only when all fields are filled out. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Book now button | When clicking the book now button on the page, the browser redirects to the booking page. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Booking Form | Checked the form submits only when all required fields are filled out. | PASS |
If not signed in | Checked to see if the user has not signed in the booking form should not show and a message displays prompting the user to signup/sign-in first. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Edit Booking Form | Checked the form submits only when all required fields are filled out. | PASS |
Form validation | Checked that the telephone number input only allows number input and not any text | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Edit booking button | Checked that the button redirects to the edit booking page with the correct booking instance. | PASS |
Cancel booking button | Checked that the button redirects to the cancel booking page with the correct booking instance. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Create profile form | Checked the form submits only when all required fields are filled out. | PASS |
If the profile has not been created | Checked to see if the user has created a profile, if not it will redirect the user to the create profile page | PASS |
Form validation | Checked that the telephone number input only allows number input and not any text | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Edit profile form | Checked the form submits only when all required fields are filled out. | PASS |
Form validation | Checked that the telephone number input only allows number input and not any text | PASS |
If the profile has not been created | Checked to see if the user has created a profile, if not it will redirect the user to the create profile page | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Register form | Checked the form submits only when all required fields are filled out. | PASS |
Sign in link | Checked the sign-in link redirects to the sign-in page. | PASS |
TEST | OUTCOME | PASS / FAIL |
---|---|---|
Media | All media assets are displayed properly, have no pixelation or stretched images and is responsive on all devices. | PASS |
Responsiveness | Check every element on-page for consistent scalability in mobile, tablet and desktop view. | PASS |
Accessibility | Checked the accessibility of the page using lighthouse | PASS |
Sign in form | Checked the form submits only when all required fields are filled out. | PASS |
Signup link | Checked the signup link redirects to the signup page. | PASS |
-
Install Django and the supporting libraries
- Install Django and Gunicorn. Gunicorn is the server I am using to run Django on Heroku.
- Install support libraries including psycopg2, this is used to connect the PostgreSQL database
- Install Cloudinary libraries, this is a host provider service that stores images
- Create the requirements.txt file. This includes the project's dependencies allowing us to run the project in Heroku.
-
Create a new, blank Django Project
- Create a new project
- Create the app
- Add restaurant_booking to the installed apps in settings.py
- Migrate all new changes to the database
- Run the server to test
-
Setup project to use Cloudinary and PostgreSQL
-
Create new Heroku app
- Sign into Heroku
- Select New
- Select create new app
- Enter a relevant app name
- Select appropriate region
- Select the create app button
-
Attach PostgreSQL database
- In Heroku go to resources
- Search for Postgres in the add-ons box
- Select Heroku Postgres
- Submit order form
-
Prepare the environment and settings.py file
- Create env.py file
- Add DATABASE_URL with the Postgres URL from Heroku
- Add SECRET_KEY with a randomly generated key
- Add SECRET_KEY and generated key to the config vars in Heroku
- Add if statement to settings.py to prevent the production server from erroring
- Replace insecure key with the environment variable for the SECRET_KEY
- Add Heroku database as the back end
- Migrate changes to new database
-
Get static media files stored on Cloudinary
- Create a Cloudinary account
- From the dashboard, copy the API Environment variable
- In the settings.py file create a new environment variable for CLOUDINARY_URL
- Add the CLOUDINARY_URL variable to Heroku
- Add a temporary config var for DISABLE_COLLECTSTATIC
- In settings.py add Cloudinary as an installed app
- Add static and media file variables
- Add templates directory
- Change DIR's key to point to TEMPALTES_DIR
- Add Heroku hostname to allowed hosts
- Create directories for media, static and templates in the project workspace
- Create a Procfile
-
I used the terminal to deploy my project locally. To do this I had to:
- Create a repository on GitHub.
- Clone the repository on your chosen source code editor (GitPod in my case) using the clone link.
- Open the terminal within GitPod
- Enter "python3 manage.py runserver into the terminal.
- Go to local host address on my web browser.
- All locally saved changes will show up here.
For the final deployment to Heroku, I had to:
- Uncomment the PostgreSQL databse from my settings.py file.
- Set debug = False in my settings.py file.
- Commit and push all files to GitHub
- In Heroku, remove the DISABLE_COLLECTSTATIC config var.
- In the deploy tab, go to the manual deploy sections and click deploy branch.
I had an issue with the deployed site and the CSS was not showing on my screen. This was rectified by restarting all dynos in Heroku.
-
Some items in the navigation bar don't have a is active red background to show the user they are on the selected page.
-
Some forms for this project is built by using the django-crispy-forms libraries therefore, some of the fields do not contain all the validation rules as I cannot target the individual inputs. For example on the edit profile form, I have add the validation rule so that the user can only enter a number, however I couldnt not figure out a way to add a min and max length value.
-
The navigation bar came from Bootstrap.
-
The JavaScript code to set the online booking form to default to the current date came from Stack Overflow.
-
The JavaScript code to disable any previous dates on the online booking form came from Demo2s.
-
The restaurant logo came from Adobe Creative Cloud Express logo maker.
-
The dragon image from the home page came from PNGItem.
-
The banner image from the home page came from PNGItem.
-
The Chinese food image on the menu page came from Google Images.
-
The Chinese food image on the menu page came from Google Maps.
-
Code Institue Tutor Support - For directing me to the correct solutions for any bugs.
-
My Mentor - For his constructive criticism and always pushing me to go further to develop my skills.