Skip to content

Commit 7f83d31

Browse files
committed
working project
1 parent e0efd0e commit 7f83d31

File tree

13 files changed

+2992
-105
lines changed

13 files changed

+2992
-105
lines changed

backups/videogames_backup_20250503_183427.sql

Lines changed: 1331 additions & 0 deletions
Large diffs are not rendered by default.

backups/videogames_backup_20250503_200840.sql

Lines changed: 1331 additions & 0 deletions
Large diffs are not rendered by default.

scripts/backup.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
import subprocess
3+
from datetime import datetime
4+
5+
6+
from dotenv import load_dotenv
7+
load_dotenv("../credentials.env")
8+
9+
db_name = os.getenv("DB_NAME")
10+
db_user = os.getenv("DB_USER")
11+
db_host = os.getenv("DB_HOST", "localhost")
12+
backup_dir = "../backups"
13+
os.makedirs(backup_dir, exist_ok=True)
14+
15+
filename = f"{backup_dir}/videogames_backup_{datetime.now():%Y%m%d_%H%M%S}.sql"
16+
17+
command = [
18+
"pg_dump",
19+
"-U", db_user,
20+
"-h", db_host,
21+
"-d", db_name,
22+
"-f", filename
23+
]
24+
25+
26+
env = os.environ.copy()
27+
env["PGPASSWORD"] = os.getenv("DB_PASSWORD")
28+
29+
print(f"🔁 Running backup to: {filename}")
30+
subprocess.run(command, env=env, check=True)
31+
print("✅ Backup complete!")
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import os
2+
import subprocess
3+
from datetime import datetime
4+
from django.core.management.base import BaseCommand
5+
from django.conf import settings
6+
7+
class Command(BaseCommand):
8+
help = "Backup the PostgreSQL database using pg_dump"
9+
10+
def handle(self, *args, **kwargs):
11+
db_settings = settings.DATABASES['default']
12+
db_name = db_settings['NAME']
13+
db_user = db_settings['USER']
14+
db_host = db_settings.get('HOST', 'localhost')
15+
db_password = db_settings['PASSWORD']
16+
17+
os.makedirs("backups", exist_ok=True)
18+
filename = f"backups/videogames_backup_{datetime.now():%Y%m%d_%H%M%S}.sql"
19+
20+
command = [
21+
"pg_dump",
22+
"-U", db_user,
23+
"-h", db_host,
24+
"-d", db_name,
25+
"-f", filename
26+
]
27+
28+
env = os.environ.copy()
29+
env["PGPASSWORD"] = db_password
30+
31+
self.stdout.write(f"Backing up to {filename}...")
32+
subprocess.run(command, env=env, check=True)
33+
self.stdout.write(self.style.SUCCESS(" Backup completed successfully!"))
Lines changed: 113 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,129 @@
11
<!DOCTYPE html>
22
<html lang="en">
3-
43
<head>
54
<meta charset="UTF-8">
6-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
8-
<title>Videogame Register</title>
9-
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
10-
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
5+
<title>ThreadingLabs Videogame App</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap" rel="stylesheet">
8+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
119
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
12-
</head>
10+
<style>
11+
body {
12+
background: linear-gradient(to right, #0f2027, #203a43, #2c5364);
13+
font-family: 'Inter', sans-serif;
14+
color: #dddddd;
15+
min-height: 100vh;
16+
margin: 0;
17+
}
18+
19+
.navbar {
20+
background-color: #121212;
21+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
22+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
23+
}
24+
25+
.jumbotron {
26+
background-color: rgba(31, 59, 88, 0.85);
27+
color: #dddddd;
28+
padding: 2rem;
29+
margin-bottom: 2rem;
30+
border-radius: 0;
31+
}
32+
33+
.card {
34+
border-radius: 1rem;
35+
background-color: rgba(30, 30, 47, 0.85);
36+
color: #dddddd;
37+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
38+
}
39+
40+
.card:hover {
41+
transform: scale(1.01);
42+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3);
43+
}
44+
45+
.table {
46+
color: #dddddd;
47+
}
48+
49+
.table-hover tbody tr:hover {
50+
background-color: rgba(255, 255, 255, 0.05);
51+
}
52+
53+
.form-control {
54+
background-color: #2b2b3b;
55+
color: #dddddd;
56+
border: none;
57+
}
58+
59+
.form-control:focus {
60+
background-color: #3a3a4f;
61+
color: #ffffff;
62+
box-shadow: none;
63+
}
1364

65+
.btn-outline-light {
66+
border-color: rgba(255, 255, 255, 0.3);
67+
}
68+
69+
footer {
70+
color: #888;
71+
text-align: center;
72+
margin-top: 4rem;
73+
}
74+
</style>
75+
</head>
1476
<body>
77+
78+
<nav class="navbar navbar-expand-lg navbar-dark">
79+
<a class="navbar-brand" href="/">ThreadingLabs</a>
80+
<div class="collapse navbar-collapse">
81+
<ul class="navbar-nav mr-auto">
82+
<li class="nav-item"><a class="nav-link" href="/videogame/list/"><i class="fas fa-gamepad"></i> Games</a></li>
83+
<li class="nav-item"><a class="nav-link" href="/videogame/reports/"><i class="fas fa-chart-bar"></i> Reports</a></li>
84+
</ul>
85+
</div>
86+
</nav>
87+
88+
<div class="jumbotron text-center shadow-sm">
1589
<div class="container">
90+
<h1 class="display-4">ThreadingLabs</h1>
91+
<p class="lead">Manage and Explore Your Videogame Collection</p>
92+
</div>
93+
</div>
1694

17-
{% if user.is_authenticated %}
18-
<p>Welcome, {{ user.username }}!</p>
19-
<form method="post" action="{% url 'logout' %}">
95+
<div class="container">
96+
{% if user.is_authenticated %}
97+
<div class="text-right mb-3">
98+
<small class="text-muted">Welcome, {{ user.username }}</small>
99+
<form method="post" action="{% url 'logout' %}" style="display: inline;">
20100
{% csrf_token %}
21-
<button type="submit" class="btn btn-link">Logout</button>
22-
</form>
23-
{% else %}
24-
<p><a href="{% url 'login' %}">Login</a></p>
25-
{% endif %}
26-
27-
<div class="col-md-10 offset-md-1 mt-5">
28-
<div class="jumbotron">
29-
<h1 class="display-4">ThreadingLabs </h1>
30-
<p class="lead font-weight-light">Threading Labs CRUD Management System</p>
31-
<hr class="my-4">
32-
{% block content %}
33-
{% endblock content %}
101+
<button class="btn btn-sm btn-outline-light">Logout</button>
102+
</form>
103+
</div>
104+
{% else %}
105+
<p><a href="{% url 'login' %}" class="text-light">Login</a></p>
106+
{% endif %}
107+
108+
<div class="row justify-content-center">
109+
<div class="col-md-10">
110+
<div class="card shadow-sm mb-5">
111+
<div class="card-body">
112+
{% block content %}
113+
{% endblock %}
114+
</div>
34115
</div>
35116
</div>
36117
</div>
118+
</div>
37119

120+
<footer>
121+
<hr class="bg-light">
122+
<small>ThreadingLabs © 2025 — All rights reserved.</small>
123+
</footer>
38124

39-
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
40-
integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
41-
crossorigin="anonymous"></script>
42-
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
43-
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1"
44-
crossorigin="anonymous"></script>
45-
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
46-
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM"
47-
crossorigin="anonymous"></script>
48-
</body>
125+
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
126+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/js/bootstrap.bundle.min.js"></script>
49127

50-
</html>
128+
</body>
129+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{% extends "videogames_register/base.html" %}
2+
{% block content %}
3+
<h2 style="color: #dddddd;">Cumulative Game Releases</h2>
4+
<table class="table table-hover" style="color: #dddddd;">
5+
<thead>
6+
<tr>
7+
<th>Year</th>
8+
<th>Games This Year</th>
9+
<th>Cumulative Total</th>
10+
</tr>
11+
</thead>
12+
<tbody>
13+
{% for row in data %}
14+
<tr>
15+
<td>{{ row.year }}</td>
16+
<td>{{ row.games_this_year }}</td>
17+
<td>{{ row.cumulative_total }}</td>
18+
</tr>
19+
{% endfor %}
20+
</tbody>
21+
</table>
22+
{% endblock %}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{% extends "videogames_register/base.html" %}
2+
{% block content %}
3+
<div class="container mt-5">
4+
<h2 class="text-center mb-4">Reporting Dashboard</h2>
5+
<div class="list-group">
6+
7+
<a href="{% url 'report_top_genres' %}" class="list-group-item list-group-item-action">
8+
Top 5 Genres by Game Count
9+
</a>
10+
11+
<a href="{% url 'report_releases_over_time' %}" class="list-group-item list-group-item-action">
12+
Games Released Per Year
13+
</a>
14+
15+
<a href="{% url 'report_cumulative' %}" class="list-group-item list-group-item-action">
16+
Cumulative Releases Over Time
17+
</a>
18+
19+
</div>
20+
</div>
21+
{% endblock %}

videogames_register/templates/videogames_register/report_releases_over_time.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% extends "videogames_register/base.html" %}
22
{% block content %}
3-
<h2>Releases Over Time</h2>
4-
<table>
3+
<h2 style="color: #dddddd;">Releases Over Time</h2>
4+
<table class="table table-hover" style="color: #dddddd;">
55
<thead>
66
<tr>
77
<th>Year</th>

videogames_register/templates/videogames_register/report_top_genres.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{% extends "videogames_register/base.html" %}
22
{% block content %}
3-
<h2>Top 5 Genres by Game Count</h2>
4-
<table>
3+
<h2 style="color: #dddddd;">Top 5 Genres by Game Count</h2>
4+
<table class="table table-hover" style="color: #dddddd;">
55
<thead>
66
<tr>
77
<th>Genre</th>
Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,38 @@
1-
21
{% extends "videogames_register/base.html" %}
32
{% load crispy_forms_tags %}
43

5-
64
{% block content %}
7-
<form action="" method="post" autocomplete="off">
8-
{% csrf_token %}
9-
{{form.title|as_crispy_field}}
10-
{{form.release_date|as_crispy_field}}
11-
<div class="row">
12-
<div class="col-md-4">
13-
{{form.description|as_crispy_field}}
14-
</div>
15-
<div class="col-md-8">
16-
{{form.genre|as_crispy_field}}
17-
</div>
18-
</div>
19-
<div class="row">
20-
<div class="col-md-8">
21-
<button type="submit" class="btn btn-success btn-block btn-lg"><i class="fa-solid fa-arrow-right"></i>
22-
Submit</button>
23-
</div>
24-
<div class="col-md-4">
25-
<a href="{% url 'videogame_list' %}" class="btn btn-secondary btn-block btn-lg">
26-
<i class="fa-solid fa-arrow-left"></i> Back to list
27-
</a>
5+
<div class="row justify-content-center">
6+
<div class="col-md-8">
7+
<div class="card shadow-sm">
8+
<div class="card-header bg-transparent">
9+
<h4 class="mb-0">
10+
{% if form.instance.pk %}
11+
<i class="fas fa-edit"></i> Update Game
12+
{% else %}
13+
<i class="fas fa-plus"></i> Add New Game
14+
{% endif %}
15+
</h4>
16+
</div>
17+
<div class="card-body">
18+
<form method="post" autocomplete="off">
19+
{% csrf_token %}
20+
{{ form.title|as_crispy_field }}
21+
{{ form.release_date|as_crispy_field }}
22+
{{ form.description|as_crispy_field }}
23+
{{ form.genre|as_crispy_field }}
24+
25+
<div class="d-flex justify-content-between mt-4">
26+
<a href="{% url 'videogame_list' %}" class="btn btn-secondary">
27+
<i class="fas fa-arrow-left"></i> Back
28+
</a>
29+
<button type="submit" class="btn btn-success">
30+
<i class="fas fa-check-circle"></i> Save
31+
</button>
32+
</div>
33+
</form>
34+
</div>
2835
</div>
2936
</div>
30-
31-
</form>
32-
{% endblock content %}
37+
</div>
38+
{% endblock %}

0 commit comments

Comments
 (0)