Purpose of your groups program
The purpose of my groups program is to help club leaders and members in Del Norte High School to communicate easily through our platform. The website helps keep control and organize events, announcements, leaderships, and members. Students can also discover a club based on their interests. This will help students increase interest in joining clubs. Often, clubs don’t have a place where they can communicate. Some clubs use instagram, some use group chat, and some clubs don’t have one. But, with this website, all the clubs will be able to communicate on the same space.
Purpose of your individual feature(s)
The purpose of my individual feature is to let presidents and other leaders of a club to announce events and make events easily. For example, if there is a competition, the president simply has to type their event on the form and click create on events tab, and other members will be able to view the event.
My feature
- when the club has been created, I can select a club to add an event
- create an event for club
- edit/update the event
- delete the event
Event Data Management and CRUD Operations
My code manages event data using Python data structures and a database. Events are stored in the database, with each row represented as a dictionary, where keys correspond to column names. The Event class handles CRUD operations like creating events with create_event() or updating them using update_event(). SQLAlchemy manages database interactions, and data is formatted into dictionaries using to_dict() for consistent frontend integration.
API Request Structure and Operations (CRUD)
API requests are structured using class-based methods for GET, POST, PUT, and DELETE operations. GET retrieves events, POST creates new ones, PUT updates existing records, and DELETE removes them. These methods use SQLAlchemy for database queries, applying sequencing, selection, and iteration for logic. Responses are formatted as JSON using Flask’s jsonify() to ensure seamless communication with the frontend.
my database table code
class Event(db.Model):
__tablename__ = 'events'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255), nullable=False)
description = db.Column(db.String(255), nullable=False)
date = db.Column(db.Date, nullable=False)
CRUD code
def read(self): # returns the result of calling the to_dict(), access an object's data
return self.to_dict()
def create(self):
"""
Creates a new event in the database.
"""
try:
db.session.add(self) # object (self) and add it to the session
db.session.commit() # save changes to db
except IntegrityError as e:
db.session.rollback() # undoes the transaction
logging.warning(f"IntegrityError: Could not create event '{self.title}' due to {str(e)}.")
return None
return self
def update(self, data):
"""
Updates the event with new data.
"""
for key, value in data.items():
if hasattr(self, key):
# Convert date string to date object if necessary
if key == 'date' and isinstance(value, str):
value = datetime.strptime(value, '%Y-%m-%d').date()
setattr(self, key, value)
try:
db.session.commit()
except IntegrityError as e:
db.session.rollback()
logging.warning(f"IntegrityError: Could not update event '{self.title}' due to {str(e)}.")
return None
return self
def delete(self):
try:
db.session.delete(self)
db.session.commit()
except IntegrityError:
db.session.rollback()
logging.warning(f"Could not delete event '{self.title}' due to IntegrityError.")
return N
Big Idea 1.4 Debugging Code and Fixing Errors
- Debugging API Requests (Validation Checks)
if not data: return {'message': 'No input data provided'}, 400 if 'title' not in data: return {'message': 'Event title is required'}, 400 if 'description' not in data: return {'message': 'Event description is required'}, 400 if 'date' not in data: return {'message': 'Event date is required'}, 400
gives me different errors and these checks prevent invalid data from being processed.
- Using Postman for API Testing and Debugging:
class EventAPI:
class _CRUD(Resource):
@token_required
def post(self):
data = request.get_json()
if not data:
return {'message': 'No input data provided'}, 400
event = Event(title=data['title'], description=data['description'], date=data['date'])
event.create()
return jsonify(event.to_dict())
These endpoints can be tested and debugged using Postman by sending requests and checking responses.
Using frontend show API request and present API response. (live demo)
The user submits a form to send data to the backend. The frontend send an API request to the backend. Backend returns responce with data. And frontend displays the information. And then, the user and other users will be able to see the event they created.
Using postman to show raw API request and RESTful response (error code(s) and JSON)
When I put all three requirements, which is title(club name), description, and date, the data saves.
The demo includes both a working request (with successful data) and an error request (demonstrating how errors are handled).
Using db_init, db_restore, db_backup to show tester data creation and data recovery.
This is my static data
and this is my dynamic data.
Then, I backup and delete the database. After, I initialize new database and restore, and it restores the dynamic data.
List requests. Use of list, dictionaries and database. Code descriptions of area where you work with list (rows) and dictionaries (columns) of the database.
Discuss formatting response data (JSON) from API into DOM
- List, Dictionaries, and Database
This is a list from my code, and
events = Event.query.all() # retrieving all events
return jsonify([event.to_dict() for event in events]) # Return a list of events as JSON
and this is dictionary format.
def to_dict(self):
"""
Convert the Event object into a dictionary format.
This method is used to return the event object as JSON in API responses.
"""
return {
"id": self.id,
"title": self.title,
"description": self.description,
"date": self.date.strftime('%Y-%m-%d')
}
This code is to query the database to retrieve records, and those records are returned as lists of dictionaries
- Formatting Response Data (JSON)
The data from the database (or from a list of dictionaries) is formatted into JSON before being sent to the frontend.
return jsonify([event.to_dict() for event in events])
the response will be like
[
{
"title": "Tech Conference",
"description": "A conference about tech.",
"date": "2025-05-20"
},
{
"title": "Music Festival",
"description": "A festival featuring music.",
"date": "2025-06-15"
}
]
- API Response Data into the DOM
Once the API sends back the JSON response, it can be displayed on a webpage by converting the JSON data into HTML elements.
DOM is the structure of the frontend of a webpage.
async function fetchAndDisplayEvents() {
const token = localStorage.getItem('authToken'); // Get the auth token
try {
// Send GET request to fetch events from API
const response = await fetch(`${pythonURI}/api/event`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}` // Send token for authentication
}
});
if (response.ok) {
const fetchedEvents = await response.json(); // Parse the response JSON
events = fetchedEvents; // Store events in global variable
eventListContainer.innerHTML = ''; // Clear existing events in the DOM
This is an example of API to DOM in my code.
The fetchAndDisplayEvents() function fetches event data from the backend API and display it.
API Call: The fetch() function sends a GET request to the backend to fetch all events.
Discuss API class (code block) you used to perform get, post, put, and delete methods.
We use get, post, put, and delete to handle CRUD operations, which include, create, read, update, and delete.
Get method returns all events stored in the events list as a JSON response.
Post method listens for POST requests to the /api/event endpoint. It expects JSON data (title, description, and date) to create a new event.
Put method is used for an event ID and the updated data.
Delete method is used for deleting event.
These are my post, put, get, and delete
def post(self):
"""
Create a new event.
"""
current_user = g.current_user # retrieve data of current user
data = request.get_json() # change json to python dictionary
if not data:
return {'message': 'No input data provided'}, 400
if 'title' not in data:
return {'message': 'Event title is required'}, 400
if 'description' not in data:
return {'message': 'Event description is required'}, 400
if 'date' not in data:
return {'message': 'Event date is required'}, 400
# Create a new event object
event = Event(title=data['title'], description=data['description'], date=data['date'])
event.create()
return jsonify(event.to_dict())
@token_required
def get(self): # display and retrieve all events
"""
Retrieve all Events.
"""
events = Event.query.all() # retrieving all events
if not events:
return {'message': 'No events found'}, 404
return jsonify([event.to_dict() for event in events]) # Return a list of events as JSON
@token_required
def put(self):
"""
Update an event.
"""
current_user = g.current_user # Retrieve data of current user
data = request.get_json() # Change JSON to Python dictionary
if not data or 'id' not in data:
return {'message': 'Event ID is required'}, 400
event = Event.query.get(data['id']) # Retrieve event by ID
if event is None:
return {'message': 'Event not found'}, 404
updated_event = event.update(data)
if updated_event:
return jsonify(updated_event.to_dict())
else:
return {'message': 'An error occurred while updating the event. Please try again.'}, 500
@token_required
def delete(self):
"""
Delete an event.
"""
current_user = g.current_user
data = request.get_json()
event = Event.query.get(data['id'])
if event is None:
return {'message': 'Event not found'}, 404
event.delete()
return jsonify({"message": "Event deleted"})
Discuss a method/procedure in class that contains sequencing, selection, and iteration.
Sequencing: Sequencing refers to executing statements in the order they are written. It ensures that actions happen one after the other in a logical way.
Selection: Choosing between different actions based on certain conditions (like “if” or “else”). It helps the program decide what to do next based on specific rules
Iteration: Repeating actions over and over, usually with loops (like “for” or “while”). It helps the program go through lists of things, or keep checking something until a condition is met.
sequence:
def initEvents(): # initEvents` function initializes the Events table with test data.
"""
Initializes the Events table with test data.
"""
with app.app_context(): # creates an application context for the app.
db.create_all()
events = [ # creates a list of Event objects
Event(title='Tech Conference', description='A conference about the latest in technology.', date='2025-05-20'),
Event(title='Music Festival', description='A festival featuring various music artists.', date='2025-06-15'),
Event(title='Art Expo', description='An expo showcasing modern art.', date='2025-07-10'),
]
for event in events:
try:
event.create()
print(f"Record created: {repr(event)}")
except IntegrityError as e:
db.session.rollback()
print(f"Records exist or duplicate error: {event.title}, {str(e)}")
create tables, define event, put it into db. each step doesnt start until previous step is done, so this is sequencing.
In this part of the post method, the statements are executed sequentially. First, an Event object is created using the provided data, and then the create() method is called to save the event in the database.
Selection ex from my code:
if not data:
return {'message': 'No input data provided'}, 400
if 'title' not in data:
return {'message': 'Event title is required'}, 400
if 'description' not in data:
return {'message': 'Event description is required'}, 400
Iteration ex:
for event in events:
response = client.post('/api/event', json=event)
if response.status_code == 200:
results['success_count'] += 1
else:
results['errors'].append(response.get_json())
results['error_count'] += 1
This loop iterates through the list of events and sends a POST request for each event. It then checks whether the request was successful
Discuss the parameters (body of request) and return type (jasonify) of the function.
- Body parameters: the parameters passed to the API functions are extracted from the body of the request, typically in JSON format.
this is an example.
const payload = {
title: eventTitle,
description: eventDescription,
date: eventDate,
};
const response = await fetch(`${pythonURI}/api/event`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(payload), // Send body parameters as JSON string
});
PUT method parameters:
data = request.get_json()
if 'id' not in data:
return {'message': 'Event ID is required'}, 400
delete method:
data = request.get_json()
event = Event.query.get(data['id'])
- RETURN TYPE
The jsonify function converts Python dictionaries or other data structures into JSON responses
return jsonify(event.to_dict()) is used to send the event data as a JSON object.
POST:
{
"title": "New Event",
"description": "A special event",
"date": "2025-02-10"
}
GET:
[
{
"title": "Event 1",
"description": "Description of Event 1",
"date": "2025-02-01"
},
{
"title": "Event 2",
"description": "Description of Event 2",
"date": "2025-02-05"
}
]
PUT:
{
"id": 1,
"title": "Updated Event",
"description": "Updated description",
"date": "2025-02-10"
}
Delete:
{
"message": "Event deleted"
}
putting request into json format.
Call to Algorithm request. Show the definition of code block to make a request.
Discuss the call/request to the method with Algorithm (fetch to endpoint).
definition of code block to make a request:
- Defining the API Endpoint: This is the URL to which the request will be sent
${pythonURI}/api/event
- Setting the Method: The HTTP method (GET, POST, PUT, DELETE, etc.) defines what action will be performed.
- authentication
- body
- make a request
- handle respose.
Algorithm for Making a Request
eventForm.addEventListener('submit', async function (e) {
e.preventDefault(); // Prevent default form submission
// Get values from form inputs
const clubName = clubNameSelect.value.trim();
const eventDescription = document.getElementById('eventDescription').value.trim();
const eventDate = document.getElementById('eventDate').value;
// Check if all required fields are filled
if (clubName && eventDescription && eventDate) {
const payload = {
title: clubName,
description: eventDescription,
date: eventDate,
};
const token = localStorage.getItem('authToken'); // Replace 'authToken' with the key where you store your token
try {
const response = await fetch(`${pythonURI}/api/event`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}` // Add the token to the request headers
},
body: JSON.stringify(payload)
});
if (response.ok) {
fetchAndDisplayEvents(); // Refresh the event list
formContainer.style.display = 'none'; // Hide the form
} else {
const error = await response.json();
alert(`Error: ${error.message}`);
}
} catch (error) {
alert('An error occurred while creating the event. Please try again.');
console.error(error);
}
} else {
alert("Please fill out all fields!");
}
});
-
Event Listener for Form Submission: This listens for the submit event on the eventForm element and prevents the default form submission behavior.
-
Retrieve Form Input Values:
const clubName = clubNameSelect.value.trim();
const eventDescription = document.getElementById('eventDescription').value.trim();
const eventDate = document.getElementById('eventDate').value;
The values from the form inputs (club name, event description, and event date) are retrieved. collecting data.
- Check If All Fields Are Filled:
if (clubName && eventDescription && eventDate) {
- Prepare the Payload (Request Body):
const payload = {
title: clubName,
description: eventDescription,
date: eventDate,
};
If the fields are filled, the data is packaged into a payload object, which will be sent as the request body in JSON format.
The payload is the data that you send to the server in the body of the request. It usually contains the information that the server needs to process the request, such as the content you want to store, update, or manipulate.
- Get Authentication Token:
const token = localStorage.getItem('authToken');
This retrieves the authentication token stored in the browser’s local storage, which is needed for authorization to create the event.
- Send the POST Request
const response = await fetch(`${pythonURI}/api/event`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(payload),
});
This sends a POST request to the backend API with the event data in the request body. The headers specify that the data is in JSON format and include the authentication token for authorization.
- Handle the Response:
if (response.ok) {
fetchAndDisplayEvents(); // Refresh the event list
formContainer.style.display = 'none'; // Hide the form
} else {
const error = await response.json();
alert(`Error: ${error.message}`);
}
If the response is successful (response.ok), it fetches and displays the updated list of events (fetchAndDisplayEvents()) and hides the form.
If the response is not successful, it parses and displays the error message.
- Error handling
catch (error) { alert('An error occurred while creating the event. Please try again.'); console.error(error); }
If any error occurs during the request (e.g., network issues), the user is alerted and the error is logged to the console.
- Validation for Empty Fields:
else {
alert("Please fill out all fields!");
}
If any field is empty, the user is prompted to fill out all the fields before submitting the form.
Discuss the return/response from the method with Algorithm (fetch) and how you handle data.
response
return jsonify(updated_event.to_dict()) # Return updated event data as JSON
When the event is successfully updated, the server returns the updated event data in the response. The event data is serialized to JSON format using jsonify().
smth like this
{
"id": 1,
"title": "Updated Event Title",
"description": "Updated Event Description",
"date": "2025-02-12"
}
How Data Is Handled in the Method
ex of PUT method
- receive request
data = request.get_json() # Change JSON to Python dictionary
- check if I put everything
if not data or 'id' not in data: return {'message': 'Event ID is required'}, 400
- check id of the event
event = Event.query.get(data['id']) # Retrieve event by ID if event is None: return {'message': 'Event not found'}, 404
- update
updated_event = event.update(data) # Update the event with the new data
Show how changing data or method triggers a different response, specifically normal conditions and error conditions.
my code for post
@token_required
def post(self):
"""
Create a new event.
"""
current_user = g.current_user # retrieve data of current user
data = request.get_json() # change json to python dictionary
if not data:
return {'message': 'No input data provided'}, 400
if 'title' not in data:
return {'message': 'Event title is required'}, 400
if 'description' not in data:
return {'message': 'Event description is required'}, 400
if 'date' not in data:
return {'message': 'Event date is required'}, 400
# Create a new event object
event = Event(title=data['title'], description=data['description'], date=data['date'])
event.create()
return jsonify(event.to_dict()), 201 # Successful event creation (Status: 201)
normal response:
{
"id": 1,
"title": "New Event",
"description": "A special event",
"date": "2025-02-10"
}
with this code
if 'title' not in data:
return {'message': 'Event title is required'}, 400
if I didn't put title, its gonna say
{
"message": "Event title is required"
}
if there is an error creating event, with this code
updated_event = event.create()
if not updated_event:
return {'message': 'An error occurred while creating the event. Please try again.'}, 500
its gonna say
{
"message": "An error occurred while creating the event. Please try again."
}