352 lines
14 KiB
Markdown
352 lines
14 KiB
Markdown
Of course. Let's build this from the ground up. This guide will be a step-by-step tutorial on how to start the project, assuming you have zero lines of code.
|
|
|
|
We will use the recommended stack: **Django** (Backend), **React** (Frontend), and **PostgreSQL** (Database), with **Vite** for the React project setup as it's faster and more modern.
|
|
|
|
### Phase 0: Prerequisites (Your Developer Machine Setup)
|
|
|
|
Before you write any code, make sure you have these tools installed on your computer:
|
|
|
|
1. **Git:** For version control. [Download Git](https://git-scm.com/downloads)
|
|
2. **Python:** (Version 3.8+). [Download Python](https://www.python.org/downloads/)
|
|
3. **Node.js and npm:** (Node LTS version). This is for managing the React project. [Download Node.js](https://nodejs.org/)
|
|
4. **PostgreSQL:** The database itself. You need to install and run the PostgreSQL server. [Download PostgreSQL](https://www.postgresql.org/download/)
|
|
5. **A Code Editor:** **Visual Studio Code (VS Code)** is highly recommended. It's free and has excellent extensions for Python/Django and React.
|
|
6. **An API Client (Optional but recommended):** Tools like **Postman** or **Insomnia** are invaluable for testing your backend API endpoints without needing a frontend.
|
|
|
|
---
|
|
|
|
### Phase 1: Project Initialization & Structure
|
|
|
|
Let's create the overall project structure. Open your terminal or command prompt.
|
|
|
|
```bash
|
|
# 1. Create a main project folder
|
|
mkdir incident-reporter-app
|
|
cd incident-reporter-app
|
|
|
|
# 2. Initialize a Git repository to track all your changes
|
|
git init
|
|
|
|
# 3. Create folders to separate the backend and frontend
|
|
mkdir backend
|
|
mkdir frontend
|
|
```
|
|
|
|
Your folder structure should look like this:
|
|
|
|
```
|
|
incident-reporter-app/
|
|
├── .git/
|
|
├── backend/ <-- Your Django project will live here
|
|
└── frontend/ <-- Your React project will live here
|
|
```
|
|
|
|
---
|
|
|
|
### Phase 2: Building the Backend Foundation (Django)
|
|
|
|
We'll start with the backend to create the data structure and API that the frontend will eventually use.
|
|
|
|
1. **Navigate into the backend folder and create a Python virtual environment.** A virtual environment keeps your project's Python packages separate from others on your system. It's a critical best practice.
|
|
|
|
```bash
|
|
cd backend
|
|
python -m venv venv # "venv" is the name of the environment folder
|
|
```
|
|
|
|
2. **Activate the virtual environment.**
|
|
* **On Windows:** `venv\Scripts\activate`
|
|
* **On macOS/Linux:** `source venv/bin/activate`
|
|
* *(Your terminal prompt should now show `(venv)` at the beginning.)*
|
|
|
|
3. **Install core Django packages.**
|
|
|
|
```bash
|
|
pip install django djangorestframework psycopg2-binary django-cors-headers
|
|
```
|
|
* `django`: The main framework.
|
|
* `djangorestframework`: A toolkit for building web APIs. A huge time-saver.
|
|
* `psycopg2-binary`: The adapter to let Django talk to your PostgreSQL database.
|
|
* `django-cors-headers`: This will be crucial later to allow your React app (on a different port) to talk to your Django API.
|
|
|
|
4. **Create the Django Project and App.** In Django, a "project" is the main container, and "apps" are components that do specific things (like handling incidents).
|
|
|
|
```bash
|
|
# Create the project. The "." means create it in the current directory.
|
|
django-admin startproject config .
|
|
|
|
# Create our first app for handling incidents
|
|
python manage.py startapp incidents
|
|
```
|
|
|
|
5. **Configure the Database in `config/settings.py`.**
|
|
* First, open PostgreSQL and create a new database for your project. Let's call it `incident_db`.
|
|
* Now, find the `DATABASES` section in your `config/settings.py` file and change it to use PostgreSQL:
|
|
|
|
```python
|
|
DATABASES = {
|
|
'default': {
|
|
'ENGINE': 'django.db.backends.postgresql',
|
|
'NAME': 'incident_db', # The name you chose for your DB
|
|
'USER': 'your_postgres_user', # Your PostgreSQL username
|
|
'PASSWORD': 'your_password', # Your PostgreSQL password
|
|
'HOST': 'localhost', # Or '127.0.0.1'
|
|
'PORT': '5432',
|
|
}
|
|
}
|
|
```
|
|
|
|
6. **Add your new apps to `INSTALLED_APPS` in `config/settings.py`.** Django needs to know about them.
|
|
|
|
```python
|
|
INSTALLED_APPS = [
|
|
# ... other apps
|
|
'rest_framework', # Add this
|
|
'corsheaders', # Add this
|
|
'incidents', # Add this (your app)
|
|
]
|
|
```
|
|
|
|
7. **Define your Data Models in `incidents/models.py`.** This is where you define your database schema using Python code.
|
|
|
|
```python
|
|
from django.db import models
|
|
from django.contrib.auth.models import User
|
|
|
|
class Incident(models.Model):
|
|
STATUS_CHOICES = (
|
|
('open', 'Open'),
|
|
('in_progress', 'In Progress'),
|
|
('closed', 'Closed'),
|
|
)
|
|
|
|
employee_name = models.CharField(max_length=200)
|
|
incident_date = models.DateTimeField()
|
|
location = models.CharField(max_length=255)
|
|
description = models.TextField()
|
|
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='open')
|
|
created_at = models.DateTimeField(auto_now_add=True)
|
|
# Link to the user who reported it
|
|
reported_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
|
|
|
|
def __str__(self):
|
|
return f"Incident at {self.location} on {self.incident_date.strftime('%Y-%m-%d')}"
|
|
```
|
|
|
|
8. **Create and run database migrations.** This process tells Django to look at your models and create the actual SQL tables in your PostgreSQL database.
|
|
|
|
```bash
|
|
python manage.py makemigrations
|
|
python manage.py migrate
|
|
```
|
|
|
|
9. **Create a superuser** so you can log into Django's built-in admin panel.
|
|
|
|
```bash
|
|
python manage.py createsuperuser
|
|
```
|
|
Follow the prompts to create a username and password.
|
|
|
|
10. **Test the Admin Panel.**
|
|
* Start the development server: `python manage.py runserver`
|
|
* Go to `http://127.0.0.1:8000/admin` in your browser.
|
|
* Log in with the superuser credentials. You can see Users, but not Incidents yet.
|
|
* **Last step:** Register your model so it shows up. In `incidents/admin.py`, add:
|
|
```python
|
|
from django.contrib import admin
|
|
from .models import Incident
|
|
|
|
admin.site.register(Incident)
|
|
```
|
|
* Now refresh the admin page. **You can now create, view, update, and delete incidents directly from this powerful, pre-built interface!** This is a huge Django win.
|
|
|
|
You have now successfully set up the entire backend foundation!
|
|
|
|
---
|
|
|
|
### Phase 3: Building the API Endpoints (Django REST Framework)
|
|
|
|
Now we need to create API endpoints so our future React app can communicate with the backend.
|
|
|
|
1. **Create a `serializers.py` file inside your `incidents` folder.** A serializer converts your complex Django model data into simple JSON that can be sent over the web.
|
|
|
|
**incidents/serializers.py:**
|
|
```python
|
|
from rest_framework import serializers
|
|
from .models import Incident
|
|
|
|
class IncidentSerializer(serializers.ModelSerializer):
|
|
class Meta:
|
|
model = Incident
|
|
fields = '__all__' # Include all fields from the model
|
|
```
|
|
|
|
2. **Create the API Views in `incidents/views.py`.** A view handles incoming requests (like GET for fetching data or POST for creating data). `ModelViewSet` from DRF is magical—it creates all the necessary endpoints for you (list, create, retrieve, update, delete).
|
|
|
|
**incidents/views.py:**
|
|
```python
|
|
from rest_framework import viewsets
|
|
from .models import Incident
|
|
from .serializers import IncidentSerializer
|
|
|
|
class IncidentViewSet(viewsets.ModelViewSet):
|
|
queryset = Incident.objects.all().order_by('-created_at')
|
|
serializer_class = IncidentSerializer
|
|
```
|
|
|
|
3. **Wire up the URLs.** We need to tell Django what URL should point to our new API view.
|
|
* **First, in your project's `config/urls.py`:**
|
|
|
|
```python
|
|
from django.contrib import admin
|
|
from django.urls import path, include
|
|
|
|
urlpatterns = [
|
|
path('admin/', admin.site.urls),
|
|
path('api/', include('incidents.urls')), # Point /api/ to our app's urls
|
|
]
|
|
```
|
|
* **Then, create a new `urls.py` file inside your `incidents` app folder.**
|
|
|
|
**incidents/urls.py:**
|
|
```python
|
|
from django.urls import path, include
|
|
from rest_framework.routers import DefaultRouter
|
|
from .views import IncidentViewSet
|
|
|
|
# Create a router and register our viewsets with it.
|
|
router = DefaultRouter()
|
|
router.register(r'incidents', IncidentViewSet, basename='incident')
|
|
|
|
# The API URLs are now determined automatically by the router.
|
|
urlpatterns = [
|
|
path('', include(router.urls)),
|
|
]
|
|
```
|
|
|
|
**Backend Checkpoint!**
|
|
* Run the server again: `python manage.py runserver`
|
|
* Go to **`http://127.0.0.1:8000/api/incidents/`** in your browser.
|
|
* You should see the **Django REST Framework's Browsable API**. You can now view existing incidents and even `POST` to create new ones directly from your browser. **You have a working API.**
|
|
|
|
---
|
|
|
|
### Phase 4: Building the Frontend (React)
|
|
|
|
Now let's switch to the frontend.
|
|
|
|
1. **Open a NEW terminal.** Do not close your Django server terminal. Navigate to the `frontend` directory.
|
|
|
|
```bash
|
|
# (In a new terminal)
|
|
cd incident-reporter-app/frontend
|
|
```
|
|
|
|
2. **Create a new React project using Vite.** Vite is a modern build tool that is significantly faster than the older `create-react-app`.
|
|
|
|
```bash
|
|
npm create vite@latest
|
|
```
|
|
* It will ask for a project name. Enter `.` to use the current directory.
|
|
* Select **React** as the framework.
|
|
* Select **JavaScript** or **TypeScript** (JavaScript is fine to start).
|
|
|
|
3. **Install dependencies and run the app.**
|
|
|
|
```bash
|
|
npm install
|
|
npm install axios react-router-dom @mui/material @emotion/react @emotion/styled # Install key libraries
|
|
npm run dev
|
|
```
|
|
* `axios`: For making API calls to your Django backend.
|
|
* `react-router-dom`: For managing navigation and pages in your app.
|
|
* `@mui/material`: A fantastic UI component library to make your app look professional quickly.
|
|
|
|
Your React app is now running, typically at `http://localhost:5173`.
|
|
|
|
---
|
|
|
|
### Phase 5: Connecting Frontend to Backend
|
|
|
|
Now, let's make React talk to Django. You will hit a **CORS error**. This is a security feature browsers enforce. Here's how to fix it.
|
|
|
|
1. **Configure `django-cors-headers` in your backend `config/settings.py`:**
|
|
```python
|
|
# Add this to the MIDDLEWARE list, high up but after SessionMiddleware
|
|
MIDDLEWARE = [
|
|
# ...
|
|
'corsheaders.middleware.CorsMiddleware', # Add this
|
|
'django.middleware.common.CommonMiddleware',
|
|
# ...
|
|
]
|
|
|
|
# Add this at the bottom of the file
|
|
CORS_ALLOWED_ORIGINS = [
|
|
"http://localhost:5173", # The address of your React app
|
|
"http://127.0.0.1:5173",
|
|
]
|
|
```
|
|
|
|
2. **Restart your Django server** for the changes to take effect.
|
|
|
|
3. **Fetch data in your React app.** Replace the code in `frontend/src/App.jsx` with a basic example to fetch and display incidents.
|
|
|
|
**frontend/src/App.jsx:**
|
|
```jsx
|
|
import { useState, useEffect } from 'react';
|
|
import axios from 'axios';
|
|
|
|
function App() {
|
|
const [incidents, setIncidents] = useState([]);
|
|
const [error, setError] = useState(null);
|
|
|
|
useEffect(() => {
|
|
// Fetch incidents from the Django API
|
|
axios.get('http://127.0.0.1:8000/api/incidents/')
|
|
.then(response => {
|
|
setIncidents(response.data);
|
|
})
|
|
.catch(error => {
|
|
console.error("There was an error fetching the data!", error);
|
|
setError("Could not load data. Is the backend server running?");
|
|
});
|
|
}, []); // The empty array means this effect runs once when the component mounts
|
|
|
|
if (error) {
|
|
return <div>Error: {error}</div>;
|
|
}
|
|
|
|
return (
|
|
<div>
|
|
<h1>Incident Reports</h1>
|
|
<ul>
|
|
{incidents.length > 0 ? (
|
|
incidents.map(incident => (
|
|
<li key={incident.id}>
|
|
<strong>{incident.location}:</strong> {incident.description} ({incident.status})
|
|
</li>
|
|
))
|
|
) : (
|
|
<p>No incidents reported yet.</p>
|
|
)}
|
|
</ul>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default App;
|
|
```
|
|
|
|
**GRAND FINALE:** Go to your React app in the browser (`http://localhost:5173`). You should see the list of incidents that you created in the Django admin panel.
|
|
|
|
### You now have a full-stack web application, with a working connection between a React frontend and a Django/PostgreSQL backend.
|
|
|
|
### Next Steps from Here:
|
|
|
|
1. **Build Out the Forms:** Use React libraries like `React Hook Form` and UI components from MUI to build the incident creation form.
|
|
2. **Implement POST Requests:** Make the form's "Submit" button send a `POST` request with `axios` to `/api/incidents/` to create new records.
|
|
3. **Add User Authentication:** Implement login/logout on the frontend that talks to Django's auth endpoints.
|
|
4. **Implement RBAC:** In your Django views, check `request.user.role` to restrict what data users can see or what actions they can perform.
|
|
5. **Build Features:** Start implementing PDF generation, the signature pad, and file uploads to S3, one by one.
|
|
6. **Containerize with Docker:** Once your app is more mature, "Dockerize" it to prepare for deployment.
|
|
7. **Deploy:** Choose a HIPAA-compliant host and deploy your application. |