added search filter and user grid, fixed an issue with files upload

This commit is contained in:
bacalhau 2026-03-04 22:42:53 +00:00
parent e9d2569c1e
commit d736ebb5bc
11 changed files with 186 additions and 38 deletions

View file

@ -1,13 +1,14 @@
from flask import Flask, render_template, request, redirect, url_for, flash, session from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from datetime import date from datetime import date
import gnupg import gnupg
import secrets import secrets
import os import os
from werkzeug.utils import secure_filename from werkzeug.utils import secure_filename
# defines where the upload folder is and creates it BASE_DIR = os.path.dirname(os.path.abspath(__file__))
UPLOAD_FOLDER = "static/uploads" UPLOAD_FOLDER = os.path.join(BASE_DIR, "static", "uploads")
os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(UPLOAD_FOLDER, exist_ok=True)
# configures the app # configures the app
@ -77,27 +78,24 @@ def calculate_age(dob: date) -> int:
return today.year - dob.year - ((today.month, today.day) < (dob.month, dob.day)) return today.year - dob.year - ((today.month, today.day) < (dob.month, dob.day))
# saves files to the upload folder and returns their URL # saves files to the upload folder and returns their URL
def save_files(username: str, profile_file, pictures_files): def save_files(username: str, profile_file, pictures_files):
# creates a path for the user inside the upload forlder
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username) user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
os.makedirs(user_folder, exist_ok=True) os.makedirs(user_folder, exist_ok=True)
# prevents unsafe characters to be used in the filename
profile_filename = secure_filename(profile_file.filename) profile_filename = secure_filename(profile_file.filename)
profile_path = os.path.join(user_folder, profile_filename) profile_path = os.path.join(user_folder, profile_filename)
# saves the profile picture to the path
profile_file.save(profile_path) profile_file.save(profile_path)
profile_url = f"/{profile_path.replace(os.sep, '/')}"
# saves all of the other pictures profile_url = f"/static/uploads/{username}/{profile_filename}"
pictures_urls = [] pictures_urls = []
for pic in pictures_files: for pic in pictures_files:
if pic.filename: if pic.filename:
filename = secure_filename(pic.filename) filename = secure_filename(pic.filename)
path = os.path.join(user_folder, filename) path = os.path.join(user_folder, filename)
pic.save(path) pic.save(path)
pictures_urls.append(f"/{path.replace(os.sep, '/')}") pictures_urls.append(f"/static/uploads/{username}/{filename}")
return profile_url, pictures_urls return profile_url, pictures_urls
@ -119,8 +117,58 @@ def pgp_encrypt_and_import(pgp_key: str, message: str):
@app.route("/") @app.route("/")
def home(): def home():
return render_template("index.html") query = User.query
country = request.args.get("country")
city = request.args.get("city")
sex = request.args.get("sex")
age_min = request.args.get("age_min")
age_max = request.args.get("age_max")
race = request.args.get("race")
likes = request.args.get("likes")
dislikes = request.args.get("dislikes")
if country:
query = query.filter(User.country.ilike(f"%{country}%"))
if city:
query = query.filter(User.city.ilike(f"%{city}%"))
if sex:
query = query.filter(User.sex==sex)
if race:
query = query.filter(User.race.ilike(f"%{race}%"))
today = date.today()
if age_min:
try:
min_age = int(age_min)
dob_max = date(today.year - min_age, today.month, today.day)
query = query.filter(User.date_of_birth <= dob_max)
except ValueError:
pass
if age_max:
try:
max_age = int(age_max)
dob_min = date(today.year - max_age - 1, today.month, today.day)
query = query.filter(User.date_of_birth >= dob_min)
except ValueError:
pass
if likes:
likes_list = [x.strip().lower() for x in likes.split(",") if x.strip()]
for like in likes_list:
query = query.filter(
text(f"JSON_CONTAINS(likes, '\"{like}\"')")
)
if dislikes:
dislikes_list = [x.strip().lower() for x in dislikes.split(",") if x.strip()]
for dislike in dislikes_list:
query = query.filter(
text(f"JSON_CONTAINS(dislikes, '\"{dislike}\"')")
)
users = query.all()
return render_template("index.html", users=users, date=date)
@app.route("/register", methods=["GET", "POST"]) @app.route("/register", methods=["GET", "POST"])
def register(): def register():

View file

@ -1,5 +1,47 @@
{% extends "page.html" %} {% extends "page.html" %}
{% block content %} {% block content %}
<h2>Main Page</h2> <h2>Discover Users</h2>
<section>
<h3>Search Users</h3>
<form method="GET" action="{{ url_for('home') }}">
<input type="text" name="country" placeholder="Country" value="{{ request.args.get('country', '') }}">
<input type="text" name="city" placeholder="City" value="{{ request.args.get('city', '') }}">
<select name="sex">
<option value="">Any Sex</option>
<option value="male" {% if request.args.get('sex')=='male' %}selected{% endif %}>Male</option>
<option value="female" {% if request.args.get('sex')=='female' %}selected{% endif %}>Female</option>
</select>
<input type="number" name="age_min" placeholder="Min Age" min="18" value="{{ request.args.get('age_min', '') }}">
<input type="number" name="age_max" placeholder="Max Age" min="18" value="{{ request.args.get('age_max', '') }}">
<input type="text" name="race" placeholder="Race" value="{{ request.args.get('race', '') }}">
<input type="text" name="likes" placeholder="Likes" value="{{ request.args.get('likes', '') }}">
<input type="text" name="dislikes" placeholder="Dislikes" value="{{ request.args.get('dislikes', '') }}">
<button type="submit">Search</button>
</form>
</section>
<section>
<h3>Users</h3>
{% if users %}
<div>
{% for user in users %}
<div>
<a href="{{ url_for('user_profile', username=user.username) }}">
<img src="{{ user.profile_picture }}" alt="{{ user.username }}" width="100"><br>
Age: {{ (date.today() - user.date_of_birth).days // 365 }}<br>
Country: {{ user.country }}
</a>
</div>
{% endfor %}
</div>
{% else %}
<p>No users found.</p>
{% endif %}
</section>
{% endblock %} {% endblock %}

View file

@ -19,9 +19,7 @@
</nav> </nav>
<body> <body>
<section>
{% block content %}{% endblock %} {% block content %}{% endblock %}
</section>
<footer>Dating Website</footer> <footer>Dating Website</footer>
</body> </body>

View file

@ -1,37 +1,97 @@
{% extends "page.html" %} {% extends "page.html" %}
{% block content %} {% block content %}
<h2>{{ user.firstname }} {{ user.lastname }}</h2>
<img src="{{ user.profile_picture }}" alt="Profile Picture" width="150"><br> <section>
<h2>{{ user.firstname }} {{ user.lastname }}</h2>
<img src="{{ user.profile_picture }}" alt="Profile Picture" style="max-width:200px; border-radius:8px;"><br><br>
<p><strong>Age:</strong> {{ (date.today() - user.date_of_birth).days // 365 }}</p>
<p><strong>Sex:</strong> {{ user.sex|capitalize }}</p>
</section>
{% if user.pictures %} {% if user.pictures %}
<h3>Pictures</h3> <section>
{% for pic in user.pictures %} <h3>Gallery</h3>
<img src="{{ pic }}" width="100"> {% for pic in user.pictures %}
{% endfor %} <img src="{{ pic }}" style="max-width:120px; margin:5px; border-radius:6px;">
{% endfor %}
</section>
{% endif %} {% endif %}
<h3>Personal Info</h3>
<p>Sex: {{ user.sex }}</p>
<p>Date of Birth: {{ user.date_of_birth }}</p>
<p>Age: {{ (date.today() - user.date_of_birth).days // 365 }}</p>
<p>Race: {{ user.race or 'Not specified' }}</p>
<h3>Location</h3> <section>
<p>Country: {{ user.country }}</p> <h3>Personal Info</h3>
<p>City: {{ user.city or 'Not specified' }}</p> <p><strong>Date of Birth:</strong> {{ user.date_of_birth }}</p>
<p><strong>Race:</strong> {{ user.race or 'Not specified' }}</p>
</section>
<h3>Physical Attributes</h3>
<p>Height: {{ user.height or 'Not specified' }} m</p>
<p>Weight: {{ user.weight or 'Not specified' }} kg</p>
<h3>Preferences</h3> <section>
<p>Preferred Age Range: {{ user.prefered_age_range or 'Not specified' }}</p> <h3>Location</h3>
<p>Likes: {{ user.likes | join(', ') if user.likes else 'Not specified' }}</p> <p><strong>Country:</strong> {{ user.country }}</p>
<p>Dislikes: {{ user.dislikes | join(', ') if user.dislikes else 'Not specified' }}</p> <p><strong>City:</strong> {{ user.city or 'Not specified' }}</p>
</section>
<section>
<h3>Physical Attributes</h3>
<p><strong>Height:</strong>
{% if user.height %}
{{ user.height }} m
{% else %}
Not specified
{% endif %}
</p>
<p><strong>Weight:</strong>
{% if user.weight %}
{{ user.weight }} kg
{% else %}
Not specified
{% endif %}
</p>
</section>
<section>
<h3>Preferences</h3>
<p><strong>Preferred Age Range:</strong>
{{ user.prefered_age_range or 'Not specified' }}
</p>
<p><strong>Likes:</strong></p>
{% if user.likes %}
<ul>
{% for like in user.likes %}
<li>{{ like }}</li>
{% endfor %}
</ul>
{% else %}
<p>Not specified</p>
{% endif %}
<p><strong>Dislikes:</strong></p>
{% if user.dislikes %}
<ul>
{% for dislike in user.dislikes %}
<li>{{ dislike }}</li>
{% endfor %}
</ul>
{% else %}
<p>Not specified</p>
{% endif %}
</section>
<section>
<h3>Contacts</h3>
<p><strong>XMPP:</strong> {{ user.xmpp }}</p>
<p><strong>Email:</strong> {{ user.email or 'Not specified' }}</p>
<p><strong>Phone:</strong> {{ user.phone or 'Not specified' }}</p>
</section>
<h3>Contacts</h3>
<p>XMPP: {{ user.xmpp }}</p>
<p>Email: {{ user.email or 'Not specified' }}</p>
<p>Phone: {{ user.phone or 'Not specified' }}</p>
{% endblock %} {% endblock %}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB