From Data to Code: Modeling EventHive
Junior Developer exploring full-stack development, backend systems, and cloud deployment. Breaking code, bending logic, and sharing secrets devs weren’t supposed to see. React | Spring Boot | Go | Python | MongoDB | SQL | Networking. Check out my GitHub and blog for projects and experiments!
Up to now, we’ve spent time thinking instead of typing.
We talked about:
who the users are
what the system stores
how users and events are connected
That work wasn’t theoretical.
It was preparation.
Because now, when we open a code editor, we’re not guessing what to build.
We’re simply giving form to ideas we already understand.
This post is where that happens.
Not signup.
Not login.
Not APIs.
Just models and relationships, written calmly and intentionally.
The Project Structure (Exactly What We’ll Use)
Before writing any code, let’s look at where things live.
eventhive/
│
├── README.md
├── requirements.txt
├── SETUP.md
│
└── src/
│
├── app.py
│
├── config/
│ └── database.py
│
└── models/
├── user.py
├── event.py
└── __init__.py
This structure is doing quiet but important work.
Everything that runs lives inside
srcConfiguration is separated from meaning
Models are grouped by what they represent, not by features
If you understand this layout, the backend already feels less intimidating.
A Note About the GitHub Repository
I’m maintaining a GitHub repository alongside this series.
Each blog post corresponds to a clean commit that contains only what we’ve discussed so far.
Post 3 introduces:
a minimal Flask app
database connection
user and event models
Nothing more.
You don’t need the repo to follow along —
but it’s there if you want a stable reference point.
Dependencies (requirements.txt)
We’re keeping this intentionally small.
flask
pymongo
python-dotenv
No frameworks layered on frameworks.
No abstractions we can’t explain yet.
Just enough to run a backend and store data.
Database Connection (src/config/database.py)
The database connection is infrastructure.
It should exist in one place, and one place only.
from pymongo import MongoClient
import os
client = MongoClient(os.getenv("MONGO_URI"))
db = client["eventhive"]
This file doesn’t contain logic.
It doesn’t know about users or events.
It simply says:
“Here is the database. Use it.”
Later, every model will depend on this — and that’s exactly how it should be.
Minimal Flask App (src/app.py)
Right now, Flask’s job is modest.
It just needs to exist and prove that everything is wired correctly.
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return {"status": "EventHive backend running"}
If this runs, we know:
Flask is set up correctly
the project structure works
we’re ready to build on top of it
That’s enough for now.
The User Model (src/models/user.py)
Let’s bring back the question we asked in the previous post:
What do we need to remember about a user?
Nothing new has appeared since then.
A user still has:
a name
an email
a password (hashed later)
a role
a creation timestamp
Now we translate that thinking into code.
from datetime import datetime
from config.database import db
class User:
def __init__(self, name, email, password, role="attendee"):
self.name = name
self.email = email
self.password = password
self.role = role
self.created_at = datetime.utcnow()
def to_dict(self):
return {
"name": self.name,
"email": self.email,
"password": self.password,
"role": self.role,
"created_at": self.created_at
}
def save(self):
return db.users.insert_one(self.to_dict())
There’s nothing clever here.
And that’s the point.
The code mirrors the idea exactly.
If you ever feel unsure about a model, the problem usually isn’t Flask —
it’s that the idea itself wasn’t clear yet.
The Event Model (src/models/event.py)
Events are where relationships show up.
from datetime import datetime
from config.database import db
class Event:
def __init__(self, title, description, date, location, created_by):
self.title = title
self.description = description
self.date = date
self.location = location
self.created_by = created_by
self.attendees = []
self.created_at = datetime.utcnow()
def to_dict(self):
return {
"title": self.title,
"description": self.description,
"date": self.date,
"location": self.location,
"created_by": self.created_by,
"attendees": self.attendees,
"created_at": self.created_at
}
def save(self):
return db.events.insert_one(self.to_dict())
Two fields matter more than the rest:
created_byattendees
These fields don’t store full users.
They store references.
And that’s enough.
Relationships
Let’s avoid database terminology for a moment.
One user can create many events
One event is created by one user
That’s why created_by stores a user ID.
Now:
One event can have many attendees
One user can attend many events
That’s why attendees is a list of user IDs.
No joins.
No embedding entire documents.
No hidden complexity.
Just clear references.
And this matters more than it looks.
Where Relationships Actually Belong
Here’s a subtle but important idea:
👉 Relationships belong in the data, not in the routes.
Routes will later use these relationships:
to check permissions
to enforce ownership
to decide what actions are allowed
But they don’t define them.
This separation keeps the system understandable as it grows.
What We’ve Done (Before Any Features)
At this point:
the backend exists
Flask is running
MongoDB is connected
users have a real shape
events have a real shape
relationships are intentional and visible
And notice something important:
We still haven’t talked about authentication.
Yet.
Because now, when we do, it will feel obvious — not overwhelming.
What Comes Next
Users exist.
Events exist.
The system knows how they relate.
Now we can finally ask:
How does a user prove who they are?
That’s where signup and login belong.
Not earlier.
Not randomly.
➡️ Next Post: Authentication Built on Real Models
And this time, it won’t feel rushed.
It’ll feel earned.