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_sqlalchemy import SQLAlchemy
from sqlalchemy import text
from datetime import date
import gnupg
import secrets
import os
from werkzeug.utils import secure_filename
# defines where the upload folder is and creates it
UPLOAD_FOLDER = "static/uploads"
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
UPLOAD_FOLDER = os.path.join(BASE_DIR, "static", "uploads")
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
# 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))
# saves files to the upload folder and returns their URL
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)
os.makedirs(user_folder, exist_ok=True)
# prevents unsafe characters to be used in the filename
profile_filename = secure_filename(profile_file.filename)
profile_path = os.path.join(user_folder, profile_filename)
# saves the profile picture to the 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 = []
for pic in pictures_files:
if pic.filename:
filename = secure_filename(pic.filename)
path = os.path.join(user_folder, filename)
pic.save(path)
pictures_urls.append(f"/{path.replace(os.sep, '/')}")
pictures_urls.append(f"/static/uploads/{username}/{filename}")
return profile_url, pictures_urls
@ -119,8 +117,58 @@ def pgp_encrypt_and_import(pgp_key: str, message: str):
@app.route("/")
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"])
def register():

View file

@ -1,5 +1,47 @@
{% extends "page.html" %}
{% 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 %}

View file

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

View file

@ -1,37 +1,97 @@
{% extends "page.html" %}
{% 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 %}
<h3>Pictures</h3>
{% for pic in user.pictures %}
<img src="{{ pic }}" width="100">
{% endfor %}
<section>
<h3>Gallery</h3>
{% for pic in user.pictures %}
<img src="{{ pic }}" style="max-width:120px; margin:5px; border-radius:6px;">
{% endfor %}
</section>
{% 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>
<p>Country: {{ user.country }}</p>
<p>City: {{ user.city or 'Not specified' }}</p>
<section>
<h3>Personal Info</h3>
<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>
<p>Preferred Age Range: {{ user.prefered_age_range or 'Not specified' }}</p>
<p>Likes: {{ user.likes | join(', ') if user.likes else 'Not specified' }}</p>
<p>Dislikes: {{ user.dislikes | join(', ') if user.dislikes else 'Not specified' }}</p>
<section>
<h3>Location</h3>
<p><strong>Country:</strong> {{ user.country }}</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 %}

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