Introduction

Frontend and backend are two essential components of a web application. The frontend is the part of the application that interacts with the user, whereas the backend is the part that handles the logic and data processing behind the scenes.

The frontend, also known as the client-side, typically consists of HTML, CSS, and JavaScript code that runs in the user's web browser. The frontend handles the user interface, page layout, and overall look of the application. It also handles user interactions, such as submitting forms, clicking buttons, and navigating between pages.

On the other hand, the backend, also known as the server-side, typically consists of a server, a database, and, in our case, APIs. The backend handles the processing and storage of data, manages user authentication and authorization, and handles business logic and rules. The backend also communicates with the frontend, providing the necessary data to render the user interface and processing user inputs.

Backend

In our class we mainly use Python and SQL/JSON to create APIs and databases. Here is a simple example of creating a SQL database and using CRUD as well.

What is CRUD

  • C: The 'C' stands for create, meaning to create a new entry in a database. In this case, creating a new entry about a certain movie or TV show.

  • R: Read, or to retrieve data from the database. In this case it is selecting the movie/TV show that you choose to display.

  • U: Update, or changing an existing entry in the database. In this case it is selecting the preexisting movie/TV show and changing the values to match what you want.

  • D: Delete, or removing data from the database. In this case it is selecting the preexisting movie/TV show and removing the entry from the database.

Films API

This API is intended to be used as a list of movies and TV shows that a person has watched. It includes attributes for the Film name(key), the year released, the language, the number of episodes, A list of the number of episodes(using pickletype), and a youtube url for the trailer. The CRUD works as follows: Create: Enter the above mentioned attributes Read: Returns all of the films and their attributes Update: Takes in new episodes watched, and a list of their names, and adds them to their respective attributes Delete: Option for deleting every film, also takes in a name to delete that film if it exists

Additional Notes

  • Frontend and backend are two distinct but interconnected parts of a web application, with different responsibilities and technologies involved.
  • The frontend is responsible for presenting information to the user and capturing user input, and is implemented using web technologies such as HTML, CSS, and JavaScript.
  • The backend is responsible for processing and storing data, handling business logic, and providing services to the frontend through APIs or other means.
  • The backend typically involves server-side technologies such as web servers, databases, and programming languages like Python, Java, or PHP.
  • Communication between the frontend and backend happens over the internet using HTTP requests and responses, and requires a clear understanding of APIs and data formats used by both sides.
from flask import Flask
import sqlite3

app = Flask(__name__)
# Connect to the SQLite database using SQLite3
conn = sqlite3.connect('films.db')

# Create a cursor object to execute SQL commands
cursor = conn.cursor()

# Create a table in the database
cursor.execute('''CREATE TABLE movies
                 (id INTEGER PRIMARY KEY, title TEXT, year INTEGER, epcount INTEGER, language TEXT, trailer TEXT, eplist TEXT)''')

# Commit the changes to the database and close the connection
conn.commit()
conn.close()
import sqlite3

def create():
    # Ask the user for movie details
    title = input("Enter the movie/tv show title: ")
    year = input("Enter the movie/tv show release year: ")
    epcount = input("Enter the movie/tv show epcount: ")
    language = input("Enter the movie/tv show language: ")
    eplist = input("Enter the movie/tv show episode names: ")
    trailer = input("Enter the link movie/tv show trailer: ")

    # Connect to the database and create a cursor to execute SQL commands
    database = 'films.db'
    connection = sqlite3.connect(database)
    cursor = connection.cursor()

    try:
        # Execute SQL to insert record into db
        cursor.execute("INSERT INTO movies (title, year, epcount, language, eplist, trailer) VALUES (?, ?, ?, ?, ?, ?)", (title, year, epcount, language, eplist, trailer))
        # Commit the changes
        connection.commit()
        print(f"{title} has been added to the list of movies.")

    except sqlite3.Error as error:
        print("Error while inserting record:", error)

    # Close cursor and connection
    cursor.close()
    connection.close()

create()
Better Call Saul has been added to the list of movies.
def read(id):
    # Connect to the database and create a cursor to execute SQL commands
    database = 'films.db'
    connection = sqlite3.connect(database)
    cursor = connection.cursor()

    # Execute SQL to select a record from db by id
    cursor.execute("SELECT * FROM movies WHERE id=?", (id,))

    # Fetch the record from the cursor
    movie = cursor.fetchone()

    # If movie exists, print its details, else print message
    if movie:
        print(f"{movie[0]}. {movie[1]}, {movie[2]}, {movie[3]}, {movie[4]}, {movie[5]}, {movie[6]}")
    else:
        print("Movie not found.")

    # Close cursor and connection
    cursor.close()
    connection.close()

read(id=1)
1. Breaking Bad, 1594, 3, English, https://ricekrispies.com, Snap, Crackle, Pop
def update(id):
    # Connect to the database and create a cursor to execute SQL commands
    database = 'films.db'
    connection = sqlite3.connect(database)
    cursor = connection.cursor()

    # Ask the user for movie details to update
    title = input("Enter the updated movie/tv show title: ")
    year = input("Enter the updated movie/tv show release year: ")
    epcount = input("Enter the updated movie/tv show epcount: ")
    language = input("Enter the updated movie/tv show language: ")
    eplist = input("Enter the updated movie/tv show episode names: ")
    trailer = input("Enter the updated link movie/tv show trailer: ")

    try:
        # Execute SQL to update the record in db
        cursor.execute("UPDATE movies SET title=?, year=?, epcount=?, language=?, eplist=?, trailer=? WHERE id=?", (title, year, epcount, language, eplist, trailer, id))
        # Commit the changes
        connection.commit()
        print("Movie updated successfully.")

    except sqlite3.Error as error:
        print("Error while updating record:", error)

    # Close cursor and connection
    cursor.close()
    connection.close()

update(id=1)
Movie updated successfully.
def delete(id):
    # Connect to the database and create a cursor to execute SQL commands
    database = 'films.db'
    connection = sqlite3.connect(database)
    cursor = connection.cursor()

    try:
        # Execute SQL to delete the record from db by id
        cursor.execute("DELETE FROM movies WHERE id=?", (id,))
        # Commit the changes
        connection.commit()
        print("Movie deleted successfully.")

    except sqlite3.Error as error:
        print("Error while deleting record:", error)

    # Close cursor and connection
    cursor.close()
    connection.close()

delete(id=2)
Movie deleted successfully.

Fetching

Overview

  • Involves retrieving data from a server or database
  • Can use different HTTP methods, such as GET, POST, PUT, and DELETE, to perform different types of operations on the server.
  • Fetching can be done through a variety of ways including AJAX, XHR, and Axios
  • In APCSP we tend to use the Fetch API over anything else
  • Fetching involves sending a request to a server using a URL (Uniform Resource Locator), which identifies the location of the resource being requested.
  • Can receive data in various formats, including JSON
  • JSON data can be parsed into objects and arrays in JavaScript, making it easy to work with and manipulate in the frontend

Python Fetch Using Request

import requests

url = "https://moviesdatabase.p.rapidapi.com/titles"

headers = {
	"content-type": "application/octet-stream",
	"X-RapidAPI-Key": "8401db6433msh3a46dd5bf23ad2ep19a280jsn48536a994246",
	"X-RapidAPI-Host": "moviesdatabase.p.rapidapi.com"
}

response = requests.get(url, headers=headers)

print(response.json())
{'page': 1, 'next': '/titles?page=2', 'entries': 10, 'results': [{'id': 'tt0001922', 'primaryImage': {'id': 'rm736959488', 'width': 800, 'height': 563, 'url': 'https://m.media-amazon.com/images/M/MV5BZDI4MmJiMmMtMzQ3Mi00N2Y0LTlkYmUtYmQ0ZTQ1NzVlZmVjXkEyXkFqcGdeQXVyMDUyOTUyNQ@@._V1_.jpg', 'caption': {'plainText': 'Darwin Karr and Gertrude McCoy in That Winsome Winnie Smile (1911)', '__typename': 'Markdown'}, '__typename': 'Image'}, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'That Winsome Winnie Smile', '__typename': 'TitleText'}, 'releaseYear': {'year': 1911, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 9, 'month': 9, 'year': 1911, '__typename': 'ReleaseDate'}}, {'id': 'tt0001539', 'primaryImage': {'id': 'rm1311052544', 'width': 800, 'height': 582, 'url': 'https://m.media-amazon.com/images/M/MV5BZGY5NzI0MzQtM2EwYi00NzY2LThiYjYtYTM5YmViZDEwMzkzXkEyXkFqcGdeQXVyMDUyOTUyNQ@@._V1_.jpg', 'caption': {'plainText': 'Caïn et Abel (1911)', '__typename': 'Markdown'}, '__typename': 'Image'}, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Caïn et Abel', '__typename': 'TitleText'}, 'releaseYear': {'year': 1911, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': None, 'month': None, 'year': 1911, '__typename': 'ReleaseDate'}}, {'id': 'tt0001636', 'primaryImage': None, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Galileo', '__typename': 'TitleText'}, 'releaseYear': {'year': 1911, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': None, 'month': 7, 'year': 1911, '__typename': 'ReleaseDate'}}, {'id': 'tt0002148', 'primaryImage': {'id': 'rm1303852544', 'width': 700, 'height': 526, 'url': 'https://m.media-amazon.com/images/M/MV5BMWY2ODg0YWEtZDVmYy00OTEwLTkxN2YtYzY5ZmRmNjVlZWYyXkEyXkFqcGdeQXVyMDUyOTUyNQ@@._V1_.jpg', 'caption': {'plainText': "Fred Mace and Mabel Normand in The Drummer's Vacation (1912)", '__typename': 'Markdown'}, '__typename': 'Image'}, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': "The Drummer's Vacation", '__typename': 'TitleText'}, 'releaseYear': {'year': 1912, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 23, 'month': 12, 'year': 1912, '__typename': 'ReleaseDate'}}, {'id': 'tt0001702', 'primaryImage': None, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': "The Indian Maiden's Lesson", '__typename': 'TitleText'}, 'releaseYear': {'year': 1911, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 22, 'month': 4, 'year': 1911, '__typename': 'ReleaseDate'}}, {'id': 'tt0001856', 'primaryImage': {'id': 'rm970923264', 'width': 800, 'height': 597, 'url': 'https://m.media-amazon.com/images/M/MV5BYmVhNGZlZTEtNjFmMS00MjEyLThkZmMtMTIwZjRjNzFkYjU3XkEyXkFqcGdeQXVyMDUyOTUyNQ@@._V1_.jpg', 'caption': {'plainText': 'Edwin August and Dorothy West in The Revenue Man and the Girl (1911)', '__typename': 'Markdown'}, '__typename': 'Image'}, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'The Revenue Man and the Girl', '__typename': 'TitleText'}, 'releaseYear': {'year': 1911, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 25, 'month': 9, 'year': 1911, '__typename': 'ReleaseDate'}}, {'id': 'tt0001790', 'primaryImage': {'id': 'rm635370240', 'width': 1748, 'height': 1340, 'url': 'https://m.media-amazon.com/images/M/MV5BMjAzMzQ3MjQxOV5BMl5BanBnXkFtZTgwMDQzNzExMzE@._V1_.jpg', 'caption': {'plainText': 'Eugénie Nau in Les misérables - Époque 1: Jean Valjean (1913)', '__typename': 'Markdown'}, '__typename': 'Image'}, 'titleType': {'text': 'Movie', 'id': 'movie', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Les misérables - Époque 1: Jean Valjean', '__typename': 'TitleText'}, 'releaseYear': {'year': 1913, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 3, 'month': 1, 'year': 1913, '__typename': 'ReleaseDate'}}, {'id': 'tt0000543', 'primaryImage': None, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Christian IXS bisættelse', '__typename': 'TitleText'}, 'releaseYear': {'year': 1906, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 19, 'month': 2, 'year': 1906, '__typename': 'ReleaseDate'}}, {'id': 'tt0002089', 'primaryImage': None, 'titleType': {'text': 'Movie', 'id': 'movie', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Carmen', '__typename': 'TitleText'}, 'releaseYear': {'year': 1912, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': None}, {'id': 'tt0000548', 'primaryImage': None, 'titleType': {'text': 'Short', 'id': 'short', 'isSeries': False, 'isEpisode': False, '__typename': 'TitleType'}, 'titleText': {'text': 'Fiskerliv i Norden', '__typename': 'TitleText'}, 'releaseYear': {'year': 1906, 'endYear': None, '__typename': 'YearRange'}, 'releaseDate': {'day': 15, 'month': 9, 'year': 1906, '__typename': 'ReleaseDate'}}]}

This is a functional fetch of a movies API from Rapid API, but the data isn't very readable. Below is an example of using Pandas to format the key values as a dataframe.

import requests
import pandas as pd

url = "https://moviesdatabase.p.rapidapi.com/titles"

headers = {
    "content-type": "application/octet-stream",
    "X-RapidAPI-Key": "8401db6433msh3a46dd5bf23ad2ep19a280jsn48536a994246",
    "X-RapidAPI-Host": "moviesdatabase.p.rapidapi.com"
}

response = requests.get(url, headers=headers)
data = response.json()

# Create an empty DataFrame
df = pd.DataFrame()

# Extract the required information and store it in a list of dictionaries
results = data["results"]
entries = []
for result in results:
    entry = {
        "id": result["id"],
        "title": result["titleText"]["text"],
        "release_year": result["releaseYear"]["year"],
    }
    entries.append(entry)

# Convert the list of dictionaries into a DataFrame
df = pd.DataFrame(entries)

print(df)



# ADD YOUR OWN COLUMN TO THE DATA FRAME
          id                                    title  release_year
0  tt0001922                That Winsome Winnie Smile          1911
1  tt0001539                             Caïn et Abel          1911
2  tt0001636                                  Galileo          1911
3  tt0002148                   The Drummer's Vacation          1912
4  tt0001702               The Indian Maiden's Lesson          1911
5  tt0001856             The Revenue Man and the Girl          1911
6  tt0001790  Les misérables - Époque 1: Jean Valjean          1913
7  tt0000543                 Christian IXS bisættelse          1906
8  tt0002089                                   Carmen          1912
9  tt0000548                       Fiskerliv i Norden          1906

Using Pandas to format a request obtained from a 3rd Party API makes it much easier to read and you can select what you want to display as well. Pandas makes it easy to access data that you feel is important.

Backend and Frontend Example

from flask import Blueprint, request, jsonify, Flask
from flask_restful import Api, Resource
from datetime import datetime
import json

film_api = Blueprint('film_api', __name__,
                   url_prefix='/api/film')

api = Api(film_api)
app = Flask(__name__)

if __name__ == '__main__':
    app.run(debug=True, port=8001)

class FilmAPI:    
    class _Create(Resource):
        def post(self):
            body = request.get_json()

            name = body.get("name")
            if name is None or len(name) < 2:
                return {'message': f'Name is missing, or is less than 2 characters'}, 210

            year = int(body.get("year"))
            if year is None or year < 1800:
                return {'message': f'Year is missing, or is before 1800'}, 210

            epcount = int(body.get("epcount"))
            if epcount is None or epcount < 1:
                return {'message': f'Episode count is missing, or is not a valid count'}, 210

            eplist = body.get("eplist").split(',')
            if eplist is None or len(eplist) < 1:
                return {'message': f'Eplist is missing, or is less than 1 element'}, 210

            language = body.get("language")
            if language is None or len(language) < 1:
                return {'message': f'Language is missing, or is less than 1 character'}, 210

            trailer = body.get("trailer")
            film = {
                "name": name,
                "year": year,
                "epcount": epcount,
                "language": language,
                "trailer": trailer,
                "eplist": eplist
            }

            with open('films.json', 'r') as f:
                films = json.load(f)

            if any(f["name"] == name for f in films):
                return {'message': f'Name {name} already exists'}, 210

            films.append(film)

            with open('films.json', 'w') as f:
                json.dump(films, f)

            return jsonify([film])


    class _Read(Resource):
        def get(self):
            with open('films.json', 'r') as f:
                films = [json.loads(line) for line in f]
            return jsonify(films)
    
    class _Update(Resource):
        def put(self):
            body = request.get_json()
            
            name = body.get("name")
            # retrieve the object to be updated using a query
            film = None
            with open('films.json', 'r') as f:
                films = [json.loads(line) for line in f]
            for f in films:
                if f['name'] == name:
                    film = f
                    break
            if film is None:
                return {'message': f'Film with name {name} not found.'}, 404
            
            #Get list and number of new episodes
            watched = body.get("watched")
            episodes = body.get("eps")
            film['watched'] = watched
            film['eps'] = episodes

            # Update data in file
            with open('films.json', 'w') as f:
                for film in films:
                    f.write(json.dumps(film))
                    f.write('\n')
            return {'message': f'Successfully updated {name}'}

    class _Delete(Resource):
        def delete(self, name):
            try:
                with open('films.json', 'r') as f:
                    films = json.load(f)
            except FileNotFoundError:
                return {'message': 'File not found.'}, 500
            
            for film in films:
                if film['name'] == name:
                    films.remove(film)
                    with open('films.json', 'w') as f:
                        json.dump(films, f, indent=2)
                    return {'message': f'Successfully deleted {name}'}
            
            # if film not found, return error
            return {'message': f'Film with name {name} not found.'}, 404   
            
    # building RESTapi endpoint
    api.add_resource(_Create, '/create')
    api.add_resource(_Read, '/')
    api.add_resource(_Update, '/update')
    api.add_resource(_Delete, '/delete/<string:name>')

Hacks

  1. Create a completely unique API with all 4 CRUD features (Create, Read, Update, Delete) DONE
  2. Create a Fetch API request for your corresponding API DONE
  3. Attempt a complete website on GitHub Pages including HTML
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

# Setup of key Flask object (app)
app = Flask(__name__)
# Setup SQLAlchemy object and properties for the database (db)
database = 'sqlite:///instance/sqlite.db'  # path and filename of database 
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = database
app.config['SECRET_KEY'] = 'SECRET_KEY'
db = SQLAlchemy()


# This belongs in place where it runs once per project
db.init_app(app)
class Car(db.Model):
    __tablename__ = 'cars'  # table name is plural, class name is singular

    # Define the User schema with "vars" from object
    id = db.Column(db.Integer, unique=True, primary_key=True)
    _uid = db.Column(db.String(255), unique=True, nullable=False)
    _brand = db.Column(db.String(255), unique=False, nullable=False)
    _color = db.Column(db.Integer, unique=False, nullable=False)
    _powersource = db.Column(db.String(255), unique=False, nullable=False)
    _type = db.Column(db.String(255), unique=False, nullable=False)
   

    # constructor of a User object, initializes the instance variables within object (self)
    def __init__(self, uid, brand, color, type, powersource):
        self._brand = brand
        self._color = color
        self._powersource = powersource
        self._type = type 
        self._uid = uid
    
    # a getter method, extracts uid from object
    @property
    def uid(self):
        return self._uid
    
    # a setter function, allows uid to be updated after initial object creation
    @uid.setter
    def uid(self, uid):
        self._uid = uid
        
    # gets the brand the car
    @property
    def brand(self):
        return self._brand
    
    # a setter function, allows brand to be updated after initial object creation
    @brand.setter
    def brand(self, brand):
        self._brand = brand

     # gets the color of the car
    @property
    def color(self):
        return self._color
    
    # a setter function, allows color to be updated after initial object creation
    @color.setter
    def color(self, color):
        self._color = color

    # gets the type of the manufacturer or the car
    @property
    def type(self):
        return self._type
    
    # a setter function, allows type to be updated after initial object creation
    @type.setter
    def type(self, type):
        self._type = type
    
    # a powersource getter
    @property
    def powersource(self):
        return self._powersource

    # a setter function to set the car's powersource
    @powersource.setter
    def powersource(self, powersource):
        self._powersource = powersource
    
            
    # output content using str(object) in human readable form, uses getter
    # output content using json dumps, this is ready for API response
    def __str__(self):
        return json.dumps(self.read())

    # CRUD create/add a new record to the table
    # returns self or None on error
    def create(self):
        try:
            # creates a person object from User(db.Model) class, passes initializers
            db.session.add(self)  # add prepares to persist person object to Users table
            db.session.commit()  # SqlAlchemy "unit of work pattern" requires a manual commit
            return self
        except IntegrityError:
            db.session.remove()
            return None

    # CRUD read converts self to dictionary
    # returns dictionary
    def read(self):
        return {
            "id": self.id,
            "brand" : self.brand,
            "color" : self.color,
            "powersource" : self.powersource,
            "type" : self.type,
            "uid": self.uid
        }
     
    def update(self, brand="", color="", powersource="", type="", uid=""):
        """only updates values with length"""
        if len(brand) > 0:
            self.brand = brand
        if len(color) > 0:
            self.color = color
        if len(powersource) > 0:
            self.powersource = powersource
        if len(type) > 0:
            self.type = type
        if len(uid) > 0:
            self.uid = uid
        db.session.add(self) # performs update when id exists\n",
        db.session.commit()
        return self

    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return None
def initCars():
    with app.app_context():
        """Create database and tables"""
        db.create_all()

        """Tester data for table"""
        c1 = Car(uid='1', brand='Acura', color='gray', powersource='ice', type='suv')
        c2 = Car(uid='2', brand='Hyundai', color='red', powersource='ice', type='sedan') 
        c3 = Car(uid='3', brand='Mazda', color='white', powersource='ice', type='sedan')
        c4 = Car(uid='4', brand='Honda', color='gray', powersource='ice', type='suv')
        c5 = Car(uid='5', brand='Dodge', color='black', powersource='ice', type='suv')
        c6 = Car(uid='6', brand='Toyota', color='white', powersource='ice', type='truck') 
        c7 = Car(uid='7', brand='Hyundai', color='blue', powersource='ice', type='sedan')
        c8 = Car(uid='8', brand='Chevrolet', color='gray', powersource='ice', type='truck')
        c9 = Car(uid='9', brand='Jeep', color='gray', powersource='ice', type='suv')
        c10 = Car(uid='10', brand='Nissan', color='silver', powersource='ice', type='sedan') 
        c11 = Car(uid='11', brand='Lexus', color='black', powersource='ice', type='sedan')
        c12 = Car(uid='12', brand='Kia', color='red', powersource='ice', type='suv')
        c13 = Car(uid='13', brand='Mazda', color='red', powersource='ice', type='truck')
        c14 = Car(uid='14', brand='Ford', color='white', powersource='ice', type='sedan') 
        c15 = Car(uid='15', brand='Kia', color='red', powersource='ice', type='truck')
        c16 = Car(uid='16', brand='Ford', color='gray', powersource='ice', type='suv')
        c17 = Car(uid='17', brand='Jeep', color='red', powersource='ice', type='truck')
        c18 = Car(uid='18', brand='Toyota', color='red', powersource='electric', type='suv') 
        c19 = Car(uid='19', brand='Kia', color='silver', powersource='ice', type='truck')
        c20 = Car(uid='20', brand='Honda', color='white', powersource='ice', type='suv')
        c21 = Car(uid='21', brand='Hyundai', color='white', powersource='ice', type='sedan')
        c22 = Car(uid='22', brand='Chevrolet', color='white', powersource='ice', type='suv') 
        c23 = Car(uid='23', brand='Jeep', color='white', powersource='ice', type='suv')
        c24 = Car(uid='24', brand='BMW', color='gray', powersource='ice', type='sedan')
        c25 = Car(uid='25', brand='Ferrari', color='yellow', powersource='ice', type='sports')
        c26 = Car(uid='26', brand='Tesla', color='red', powersource='electric', type='suv') 
        c27 = Car(uid='27', brand='Tesla', color='blue', powersource='electric', type='suv')
        c28 = Car(uid='28', brand='Ford', color='white', powersource='electric', type='truck')
        c29 = Car(uid='29', brand='Ford', color='blue', powersource='electric', type='truck')
        c30 = Car(uid='30', brand='Audi', color='black', powersource='electric', type='suv') 
        c31 = Car(uid='31', brand='Ferrari', color='red', powersource='electric', type='sports')
        c32 = Car(uid='32', brand='Mercedes', color='silver', powersource='electric', type='sedan')
        c33 = Car(uid='33', brand='Mazda', color='silver', powersource='electric', type='suv')
        c34 = Car(uid='34', brand='Nissan', color='blue', powersource='electric', type='suv') 
        c35 = Car(uid='35', brand='Subaru', color='red', powersource='electric', type='suv')

        cars = [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30, c31, c32, c33, c34, c35]

        """Builds sample car/note(s) data"""
        for car in cars:
            try:
                object = car.create()
                print(f"Created new uid {object.uid}")
                
            except:  # error raised if object nit created
                '''fails with bad or duplicate data'''
                print(f"Records exist uid {car.uid}, or error.")
initCars()
def find_by_caruid(uid):
    with app.app_context():
        car = Car.query.filter_by(_uid=uid).first()
    return car # returns user object

def createCar():
    uid = input("Enter your car id:")
    car = find_by_caruid(uid)
    try:
        print("Found\n", car.read())
        return
    except:
        pass # keep going

    # request value that ensure creating valid object
    brand = input("What brand is the car?")
    color = input("What color is the car?")
    powersource = input("What is the car's powersource?")
    type = input("What type of car is it?") 
    
    # Initialize User object before date
    car = Car(brand=brand,
                color=color, 
                powersource=powersource,
                type=type,
                uid=uid
                )
       
    # write object to database
    with app.app_context():
        try:
            object = car.create()
            print("Created\n", object.read())
        except:  # error raised if object not created
            print("Unknown error powersource {uid}")
        
createCar()
def readCar():
    with app.app_context():
        table = Car.query.all()
    json_ready = [car.read() for car in table] # "List Comprehensions", for each car add car.read() to list
    return json_ready

readCar()
def updateCar(uid, new_brand, new_color, new_powersource, new_type):
    with app.app_context():
        car = db.session.query(Car).filter_by(_uid=uid).first()
        try:
            print("Found\n", car.read())

            car.update(new_brand, new_color, new_powersource, new_type)
        
            return
        except:
            pass # keep going

uid = input("Enter your car id:")

new_brand = input("Enter new brand:")
new_color = input("Enter new color:")
new_powersource = input("Enter new powersource:")
new_type = input("Enter new type:")

updateCar(uid, new_brand, new_color, new_powersource, new_type)
def deleteCar(uid):
    with app.app_context():
        car = db.session.query(Car).filter_by(_uid=uid).first()
        try:
            print("Found\n", car.read())

            car.delete()
        
            return
        except:
            pass # keep going

uid = input("Enter your car uid:")
deleteCar(uid)
'''fetch request'''
import pandas as pd
import requests

def fetch():
    '''Obtain data from an endpoint'''
    url = "https://finalssvgcars.duckdns.org/api/cars/"
    fetch = requests.get(url)
    json = fetch.json()

    # filter data for requirement
    df = pd.DataFrame(json)  # filter endpoint for brand
    print(df.loc[0:5, 'brand':'type']) # show row 0 through 5 and columns brand through type
    
fetch()
     brand  color  id image powersource  pricerange   type
0    Acura   gray   1     1         ice           2    suv
1  Hyundai    red   2     2         ice           1  sedan
2    Mazda  white   3     3         ice           1  sedan
3    Honda   gray   4     4         ice           1    suv
4    Dodge  black   5     5         ice           2    suv
5   Toyota  white   6     6         ice           2  truck