Skip to content

Commit

Permalink
#29 Refactor views.py and other modules to OOP struct (#44)
Browse files Browse the repository at this point in the history
* #29 Refactor views.py and other modules to OOP struct

* #42 Add placeholder text for reservation form & style input width to be consistent

- [] Update forms.py

* #29 Extract handler class from Views

* #29 Update bookings table data with heading

* #29 Explicit type handling for views & handler modules

Fix some pylint issues

* #29 Upgrade requirements.txt

* #29 Fix lint issues
  • Loading branch information
conorheffron authored Sep 18, 2024
1 parent bb70581 commit f3eb150
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 114 deletions.
5 changes: 2 additions & 3 deletions booking-sys/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls import handler404
from django.views.static import serve
from restaurant import views
from restaurant import handlers

handler404 = views.handler404
handler404 = handlers.Handlers.handler404

urlpatterns = [
path('admin/', admin.site.urls),
Expand Down
11 changes: 9 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
asgiref==3.8.1
astroid==3.2.4
certifi==2024.7.4
charset-normalizer==3.3.2
defusedxml==0.7.1
dill==0.3.8
distlib==0.3.8
Django==5.1.1
djangorestframework==3.15.2
djangorestframework-xml==2.0.0
filelock==3.15.4
idna==3.10
isort==5.13.2
mccabe==0.7.0
mysqlclient==2.2.4
pipenv==2024.0.1
platformdirs==4.2.2
pylint==3.2.7
setuptools==73.0.0
pylint-django==2.5.5
pylint-plugin-utils==0.8.2
pytz==2024.2
requests==2.32.3
setuptools==75.1.0
sqlparse==0.5.1
tomlkit==0.13.2
virtualenv==20.26.3
urllib3==2.2.3
virtualenv==20.26.3
28 changes: 24 additions & 4 deletions restaurant/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Reservation Form Module
"""
from datetime import datetime
import pytz
from django import forms

class ReservationForm(forms.Form):
Expand All @@ -11,7 +12,26 @@ class ReservationForm(forms.Form):
reservation_date The booking date.
reservation_slot The booking time slot (HH:MM:SS).
"""
first_name = forms.CharField(min_length=3, max_length = 15)
reservation_date = forms.DateField(widget=forms.widgets.DateInput(
attrs={'type': 'date', 'format':['%d-%m-%Y'], 'value': datetime.now().date()}))
reservation_slot = forms.TimeField(widget=forms.widgets.TimeInput(attrs={'type': 'time'}))
tz = pytz.timezone('UTC')
tz_time = tz.localize(datetime.now())
london_tz = pytz.timezone('Europe/London')
london_time = tz_time.astimezone(london_tz)

first_name = forms.CharField(max_length=15,
min_length=3,
widget=forms.widgets.TextInput
(attrs={'style': 'width:45%',
'placeholder': 'Enter Name...'}),
label='')

reservation_date = forms.DateField(label='', widget=forms.widgets.DateInput(
attrs={'type': 'date',
'format':['%d-%m-%Y'],
'value': london_time.date(),
'style': 'width:45%'}))

reservation_slot = forms.TimeField(label='', widget=forms.widgets.TimeInput(
attrs={'type': 'time',
'format':['HH:mm'],
'value': london_time.strftime('%H:%M'),
'style': 'width:45%'}))
25 changes: 25 additions & 0 deletions restaurant/handlers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""booking-sys handlers module for Mapping & Logic for 4xx to 5xx HTTP status codes
"""
import logging
from django.shortcuts import render
from django.core.handlers.wsgi import WSGIRequest
from django.urls.exceptions import Resolver404
from django.http import HttpResponse

logger = logging.getLogger(__name__)

class Handlers():
"""Handlers for HTTP Error codes like 404 not found, 401 forbidden etc.
"""

@classmethod
def handler404(cls, request:WSGIRequest, exception:Resolver404) -> HttpResponse:
"""Resolve bad request path
Parameters
----------
request : WSGIRequest
exception: Resolver404
"""
uri = request.get_full_path
logger.error('Bad Request URI path: %s', uri)
return render(request, 'error.html', {'uri': uri}, status=404)
6 changes: 3 additions & 3 deletions restaurant/static/js/reservations.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ function renderTableBookings(bookings) {
if (bookings.length > 0) {
var dynamoT = '<tbody>'
dynamoT += '<tr>';
dynamoT += '<th>First Name</td>';
dynamoT += '<th>Reservation Date</td>';
dynamoT += '<th>Reservation Time</td>';
dynamoT += '<th>Name</td>';
dynamoT += '<th>Booking Date</td>';
dynamoT += '<th>Booking Time</td>';
dynamoT += '</tr>';
for (i = 0; i < bookings.length; i++) {
dynamoT += '<tr>';
Expand Down
3 changes: 2 additions & 1 deletion restaurant/templates/booking.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</div>

<div id="bookings" class="container pt-5">
<h1>Make a Reservation</h1>
<h3>Make a Reservation</h1>
<form method="POST" id="form">
{% csrf_token %}
{{ form.as_p }}
Expand All @@ -30,6 +30,7 @@ <h1>Make a Reservation</h1>
</div>

<div id="reservations-by-date" class="container pt-5 table mt-3 table-sm table_col_padding">
<h3>Bookings by Date</h3>
<table>
<tbody id="tableData"></tbody>
</table>
Expand Down
2 changes: 1 addition & 1 deletion restaurant/templates/navbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<div class="navbar-nav">
<a class="nav-link" href="/">Home</a>
<a class="nav-link" href="/reservations">Reservations</a>
<a class="nav-link" href="/admin">Login</a>
<a class="nav-link" target="_blank" href="/admin">Login</a>
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions restaurant/templates/reservations.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
</div>

<div id="bookings" class="container pt-5 table mt-3 table-sm table_col_padding">
<h3>All Bookings</h3>
<table>
<tr>
<th>First Name</th>
Expand All @@ -33,6 +34,7 @@
</tr>
{% endfor %}
</table>
<br />
<button type="button" class="btn btn-primary" onClick="refresh()">Refresh</button>
</div>
<body>
12 changes: 6 additions & 6 deletions restaurant/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
booking-sys Views Mapping & Logic
"""
from django.urls import path
from restaurant import views
from restaurant.views import Views

urlpatterns = [
path('', views.form_view, name="home"),
path('book/', views.form_view, name="book"),
path('reservations/', views.reservations_view, name="reservations"),
path('bookings/<str:date>/', views.bookings_view, name='bookings_by_date'),
path('bookings', views.table_view, name='bookings_by_date')
path('', Views.form_view, name="home"),
path('book/', Views.form_view, name="book"),
path('reservations/', Views.reservations_view, name="reservations"),
path('bookings/<str:date>/', Views.bookings_view, name='bookings_by_date'),
path('bookings', Views.table_view, name='bookings_by_date')
]
193 changes: 99 additions & 94 deletions restaurant/views.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,116 @@
"""booking-sys Views Mapping & Logic
"""booking-sys views Mapping & Logic
"""
from datetime import datetime
import logging
from django.http import JsonResponse
from django.shortcuts import render
from django.core.handlers.wsgi import WSGIRequest
from restaurant.forms import ReservationForm
from .models import Reservation

logger = logging.getLogger(__name__)

def handler404(request, exception):
"""Resolve bad request path
Parameters
----------
request : Requests https://requests.readthedocs.io/en/latest/
class Views():
"""Views class for Views Mapping & Logic
"""
uri = request.get_full_path
logger.error('Bad Request URI path: %s', uri)
return render(request, 'error.html', {'uri': uri}, status=404)

def table_view(request):
"""GET bookings by date request parameter
Parameters
----------
request : Requests
"""
date = request.GET.get("date", datetime.today().date())
return find_bookings_by_date(date)
@classmethod
def table_view(cls, request:WSGIRequest):
"""GET bookings by date request parameter
Parameters
----------
request : Requests
"""
date = request.GET.get("date", datetime.today().date())
return cls.__find_bookings_by_date(cls, date)

def bookings_view(request, date):
"""GET bookings by date request path variable
Parameters
----------
request : Requests
date: The date in format %y-%m-%d i.e. 2024-09-07
"""
logger.info('Request information (%s)', request)
return find_bookings_by_date(date)
@classmethod
def bookings_view(cls, request:WSGIRequest, date):
"""GET bookings by date request path variable
Parameters
----------
request : Requests
date: The date in format %y-%m-%d i.e. 2024-09-07
"""
logger.info('Request information (%s)', request)
return cls.__find_bookings_by_date(cls, date)

def find_bookings_by_date(date):
"""Bookings by date and return JSON response
Parameters
----------
date: The date in format %y-%m-%d i.e. 2024-09-07
"""
reservations_by_date = Reservation.objects.filter(reservation_date=date)
data = list(reservations_by_date.values('first_name', 'reservation_date', 'reservation_slot'))
logger.info('GET by date (%s) Query set results: %s', date, data)
return JsonResponse({
'message': 'success',
'reservations': data
})
@classmethod
def reservations_view(cls, request:WSGIRequest):
"""Resolve all reservations view data request
Parameters
----------
request : Requests
"""
data = list(Reservation.objects.all().values(
'first_name', 'reservation_date', 'reservation_slot'))
logger.info('GET All Query set results: %s', data)
return render(request, 'reservations.html', {'reservations': data})

def reservations_view(request):
"""Resolve all reservations view data request
Parameters
----------
request : Requests
"""
data = list(Reservation.objects.all().values(
'first_name', 'reservation_date', 'reservation_slot'))
logger.info('GET All Query set results: %s', data)
return render(request, 'reservations.html', {'reservations': data})
@classmethod
def form_view(cls, request:WSGIRequest):
"""Resolve make a reservation form submit
Parameters
----------
request : Requests
"""
form = ReservationForm()
# POST request logic
if request.method == 'POST':
form = ReservationForm(request.POST)
logger.info(request.POST)
if form.is_valid():
# clean & extract form data
form_data = form.cleaned_data
booking_date = form_data['reservation_date']
booking_slot = form_data['reservation_slot']

def form_view(request):
"""Resolve make a reservation form submit
Parameters
----------
request : Requests
"""
form = ReservationForm()
# POST request logic
if request.method == 'POST':
form = ReservationForm(request.POST)
logger.info(request.POST)
if form.is_valid():
# clean & extract form data
form_data = form.cleaned_data
booking_date = form_data['reservation_date']
booking_slot = form_data['reservation_slot']
# booking flow logic
reservations_by_date = Reservation.objects.filter(
reservation_date=booking_date, reservation_slot=booking_slot)
message = ''
if reservations_by_date.exists():
message = 'Booking Failed - Already Reserved'
else:
# map form object to model & save to DB
reservation = Reservation(
first_name = form_data['first_name'],
reservation_date = booking_date,
reservation_slot = booking_slot,
)
reservation.save()
message = 'Booking Complete'
# POST response JSON
data = list(Reservation.objects.filter(reservation_date=booking_date).values(
'first_name', 'reservation_date', 'reservation_slot'))
logger.info('POST Query set results: %s', data)
return JsonResponse({
'message': message,
'reservations': data
})
else:
# Bookings view default logic
reservations = Reservation.objects.all()
data = list(reservations.values_list('first_name',
'reservation_date',
'reservation_slot'))
logger.info('GET Query set results: %s', data)
return render(request, 'booking.html', {'form': form,
'reservations': reservations})

# booking flow logic
reservations_by_date = Reservation.objects.filter(
reservation_date=booking_date, reservation_slot=booking_slot)
message = ''
if reservations_by_date.exists():
message = 'Booking Failed - Already Reserved'
else:
# map form object to model & save to DB
reservation = Reservation(
first_name = form_data['first_name'],
reservation_date = booking_date,
reservation_slot = booking_slot,
)
reservation.save()
message = 'Booking Complete'
# POST response JSON
data = list(Reservation.objects.filter(reservation_date=booking_date).values(
'first_name', 'reservation_date', 'reservation_slot'))
logger.info('POST Query set results: %s', data)
return JsonResponse({
'message': message,
'reservations': data
})
else:
# Bookings view default logic
reservations = Reservation.objects.all()
data = list(reservations.values_list('first_name', 'reservation_date', 'reservation_slot'))
logger.info('GET Query set results: %s', data)
return render(request, 'booking.html', {'form': form, 'reservations': reservations})
def __find_bookings_by_date(self, date):
"""Bookings by date and return JSON
response (private method)
Parameters
----------
date: The date in format %y-%m-%d i.e. 2024-09-07
"""
reservations_by_date = Reservation.objects.filter(reservation_date=date)
data = list(reservations_by_date.values('first_name',
'reservation_date',
'reservation_slot'))
logger.info('GET by date (%s) Query set results: %s', date, data)
return JsonResponse({
'message': 'success',
'reservations': data
})

0 comments on commit f3eb150

Please sign in to comment.