Trips App

Overview

The idea of this project is to have one place (a database) to save info about my trips and flight searches. Then to build a Django app to display and interact with that info.
GitHub repo: trips.
A work in progress version of the app running here: Trips (creds: user: demo / pass: demo2022).

The project is centered on the Trips app and inside the Trips app the main model is Trip. There are, in all, ten models. The project itself has three apps: Trips (the main app), Base (a general purpose app), and Users (and app handling the users related properties).

The Trip App Models

The Trip model

This would be the main model of the project. The goal with this model is to have a table which captures most of the useful information related to a trip.
Practically, the attributes of this model can be grouped in three categories: general info about the trip, info about the outgoing leg of the trip, and info about the returning leg of the trip.

The attributes related to the details of the trip, the general info, are these:

  • name - not unique
  • orig and dest for the departing and, respectively, arriving point of the trip.
  • trav for the number of travellers
  • price and currency
  • date_found and source_found. These two fields are useful both for past trips and for saved search results.
  • a notes attribute

The next two groups of attributes are related to the outgoing and returning parts of the trip:

  • out_dep_date and out_dep_day
  • out_arr_date and out_arr_day
  • out_stop_duration and out_duration
  • out_price and out_class
  • out_first_flight, out_first_flight_dep_term, and out_first_flight_arr_term
  • out_second_flight, out_second_flight_dep_term, and out_second_flight_arr_term

and for returning half of the trip:

  • ret_dep_date and ret_dep_day
  • ret_arr_date and ret_arr_day
  • ret_stop_duration and ret_duration
  • ret_price and ret_class
  • ret_first_flight, ret_first_flight_dep_term, and ret_first_flight_arr_term
  • ret_second_flight, ret_second_flight_dep_term, and ret_second_flight_arr_term

This model tries to cover both, one-way trip and return trip.

The Flight Model

This model has nine attributes and it tries to represent what I needed to save for the flights I used or I found in my searches.

  • name
  • duration
  • airline
  • airplane
  • depart_airport and depart_time
  • arrive_airport and arrive_time
  • a notes field

Initially, all of the attributes were CharField but later I found it useful to have separate tables for airplane, airline, airport and the related airport terminal as well as city for location.

The City, Airline, Airplane, Airport, and AirportTerminal Models

These are smaller models with just a few attributes.

The City model attributes: name (unique), country, prov_st, and notes.
The Airline model attributes: name (unique), country, and notes.
The Airplane model attributes: name (unique), and notes.
The Airport model attributes: name (unique), code, city, and notes.
The AirportTerminal model attributes: name (not unique), airport, and notes.

The Traveller and Seat models

The idea with these two models is to save in two different tables which family member was on a specific trip and which seat was on the flight. This looks interesting to save.

The Traveller model attribute: name (unique), and notes.
The Seat model attributes: seat_number, traveller, trip, flight, and notes.

Models Relationships and Dependencies

Relationships between models

City
Airline
Airplane
Airport         - city ==> City - PROTECT
AirportTerminal - airport ==> Airport - PROTECT
Flight          - airline ==> Airline - PROTECT
                - airplane ==> Airplane - PROTECT
                - depart_airport ==> Airport - PROTECT
                - arrive_airport ==> Airport - PROTECT
TripSource
TripClass       - airline ==> Airline - PROTECT
Trip            - orig ==> City - PROTECT
                - dest ==> City - PROTECT
                - source_found ==> TripSource - PROTECT
                - out_class ==> TripClass - SET_NULL
                - out_first_flight ==> Flight - PROTECT
                - out_first_flight_dep_term ==> AirportTerminal - SET_NULL
                - out_first_flight_arr_term ==> AirportTerminal - SET_NULL
                - out_second_flight ==> Flight - PROTECT
                - out_second_flight_dep_term ==> AirportTerminal - SET_NULL
                - out_second_flight_arr_term ==> AirportTerminal - SET_NULL
                - ret_class ==> TripClass - SET_NULL
                - ret_first_flight ==> Flight - PROTECT
                - ret_first_flight_dep_term ==> AirportTerminal - SET_NULL
                - ret_first_flight_arr_term ==> AirportTerminal - SET_NULL
                - ret_second_flight ==> Flight - PROTECT
                - ret_second_flight_dep_term ==> AirportTerminal - SET_NULL
                - ret_second_flight_arr_term ==> AirportTerminal - SET_NULL
Traveller
Seat            - traveller ==> Traveller - PROTECT
                - trip ==> Trip - PROTECT
                - flight ==> Flight - PROTECT

Dependencies:

City dependencies:              Airport, Trip  
Airline dependencies:           Flight, TripClass  
Airplane dependencies:          Flight  
Airport dependencies:           AirportTerminal, Flight, Trip  
AirportTerminal dependencies:   none (Trip is SET_NULL)  
Flight dependencies:            Trip, Seat  
TripSource dependencies:        Trip  
TripClass dependencies:         none (Trip is SET_NULL)  
Trip dependencies:              Seat  
Traveller dependencies:         none  
Seat dependencies:              none  

Base App

In this project base app doesn't have any models.

Views in Base App

The base app has several views which are subclassed by the views in the trips app, views for error pages, and a search view.

BaseItemsList View

This class is subclassing the generic ListView and is used to display items either as a list of links or as boxes.
For template it's using base_items_list_boxes.html as a generic way to display the items in

It is subclassed by the folowing view classes in the trips app:

  • AirplaneList
  • TripSourceList
  • TripClassList
  • TravellerList

BaseItemsTable View

This class is subclassing the generic View and is used to display the items in a table created with django_tables2. For template it's using base_items_list_table.html.

It is subclassed by the following view classes in the trips app:

  • CityTable
  • AirlineTable
  • AirportTable
  • AirportTerminalTable
  • FlightTable
  • SeatTable

BaseItemsSearchResults View

This class is subclassing the generic View and is used to display the search results in tables. For template it's using base_search_results.html.

It is subclassed by the following view classes in the trips app:

  • CitySearchResults
  • AirlineSearchResults
  • AirplaneSearchResults
  • AirportSearchResults
  • AirportTerminalSearchResults
  • FlightSearchResults
  • TripSourceSearchResults
  • TripClassSearchResults
  • TripSearchResults
  • TravellerSearchResults
  • SeatSearchResults

BaseItemCreateWithPopup

This class is subclassing the generic CreateView. It is used to display a popup window (same like Django admin) to create a new item from within a form. It's used with forms for models which have ForeignKey relationships to other models.

It is subclassed by the following views in the trips app:

  • CityCreate
  • AirlineCreate
  • AirplaneCreate
  • AirportCreate
  • AirportTerminalCreate
  • FlightCreate
  • TripSourceCreate
  • TripClassCreate
  • TravellerCreate

BaseItemEdit

This class is subclassing the generic UpdateView. It is used for editing an existing instance.
It is subclassed by the following views from trips app:

  • CityEdit
  • AirlineEdit
  • AirplaneEdit
  • AirportEdit
  • AirportTerminalEdit
  • FlightEdit
  • TripSourceEdit
  • TripClassEdit
  • TripEdit
  • TravellerEdit
  • SeatEdit

Practically all the edit views from the trips app are using this class from the base app. This class adds to the get_context_data method the type of verbose name of the model and that is used later in the templates.

Error pages Views

  • custom_page_not_found_view - for 404 error
  • custom_error_view - for 500 error
  • custom_permission_denied_view - for 403 error
  • custom_bad_request_view - for 400 error

They work together with the handler definition from the project urls.

handler404 = 'base.views.custom_page_not_found_view'
handler500 = 'base.views.custom_error_view'
handler403 = 'base.views.custom_permission_denied_view'
handler400 = 'base.views.custom_bad_request_view'

Search View

The role of this view is to display the results of site-wide searches in tables for each of the model instances for whcih there are results.

Other Components in Base App

Forms

One form defined here, the Search Form. Used in the search view.

Context Processors

One definition for a context processor - the one used to get the project version from settings.py and make it available to all the templates. It's result is used in the footer to display the version number.

Widgets

Four custom widgets are defined in the base app for this project

RelatedFieldWidgetSingle

It's subclassing the Select widget.
This is used in the forms with fields that have ForeignKey and it displays (like in Django Admin) a plus sign to create a new object.

SplitDurationWidget and MultiValueDurationField

Used in the filter form in the trips list view.