This commit is contained in:
Mikołaj Kaczmarek
2025-06-15 22:01:27 +02:00
parent 8c7c4ceb19
commit 1fb8cac71f
15 changed files with 2 additions and 2 deletions

27
src/db_utils.py Normal file
View File

@@ -0,0 +1,27 @@
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# Inicjalizacja BD
engine = create_engine("sqlite:///mojabaza.db", echo=True)
Base = declarative_base()
# Schemat BD
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String, index=True)
password = Column(String)
def __init__(self, username, password):
self.username = username
self.password = password
# Metoda do tworzenia sesji...
def create_db_session():
Session = sessionmaker(bind=engine)
session = Session()
return session
Base.metadata.create_all(engine)

82
src/main.py Normal file
View File

@@ -0,0 +1,82 @@
import flask
from flask import Flask, render_template, request, session
import os
import traceback
import json
import random
import datetime
from src.db_utils import create_db_session, User
from src.weather_api import get_weather
# Inicjalizacja web app
app = flask.Flask(__name__,
template_folder='templates',
static_folder='static')
app.secret_key = os.urandom(24)
@app.route('/')
def test():
return "<h1>To jesty test aplikacji!</h1>"
# Przekazywanie prostych parametrów...
@app.route('/hello/<name>')
def hello(name):
return "<h1>Hello, %s!</h1>" % str(name)
# Proste logowanie zdarzeń...
plik_logu = "logi.txt"
@app.route('/logi/<name>')
def logi(name):
with open(plik_logu, 'a') as file:
now = datetime.datetime.now()
file.write(now.isoformat() + ": odwiedziny przez " + name + "\n")
return "<h1>Hello z logiem, %s!</h1>" % name
# Obsługa sesji...
@app.route("/zaloguj")
def zaloguj():
session["zalogowany"] = True
if session["zalogowany"]:
return render_template("frontpage.html")
else:
return "Użytkownik niezalogowany!"
@app.route("/wyloguj")
def wyloguj():
session["zalogowany"] = False
return "Użytkownik wylogowany!"
@app.route("/logowanie")
def logowanie():
return render_template("logowanie.html")
@app.route("/login", methods=["POST"])
def login():
# Twózs obiekt sesji BD...
sqlsession = create_db_session()
# Zdefiniuj zapytanie do BD...
query = sqlsession.query(User).filter(User.username == request.form["username"])
# Zaadaj zapytanie...
user = query.first()
result = "<h1>Login</h1>"
if request.form["username"]:
result += "<p>" + request.form["username"] + "</p>\n"
if request.form["password"]:
result += "<p>" + request.form["password"] + "</p>\n"
return result
@app.route("/pogoda")
def pogoda():
temp, humidity, type, rain = get_weather()
return render_template("pogoda.html", temp=temp, humid=humidity, weathertype=type, rain=rain)
if __name__ == '__main__':
app.run(debug=False)

BIN
src/static/humid.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
src/static/rain.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

132
src/static/style.css Normal file
View File

@@ -0,0 +1,132 @@
* {
box-sizing: border-box;
}
*:focus {
outline: none;
}
body {
font-family: Arial;
background-color: #3498DB;
padding: 50px;
font-size: 0.7em;
font-weight: 200;
color: #777;
}
.login {
margin: 20px auto;
width: 300px;
}
.login-screen {
background-color: #FFF;
padding: 20px;
border-radius: 5px
}
.app-title {
text-align: center;
color: #777;
}
.login-form {
text-align: center;
}
.control-group {
margin-bottom: 10px;
}
input {
text-align: center;
background-color: #ECF0F1;
border: 2px solid transparent;
border-radius: 3px;
font-size: 16px;
font-weight: 200;
padding: 10px 0;
width: 250px;
transition: border .5s;
}
input:focus {
border: 2px solid #3498DB;
box-shadow: none;
}
.btn {
border: 2px solid transparent;
background: #3498DB;
color: #ffffff;
font-size: 16px;
line-height: 25px;
padding: 10px 0;
text-decoration: none;
text-shadow: none;
border-radius: 3px;
box-shadow: none;
transition: 0.25s;
display: block;
width: 250px;
margin: 0 auto;
}
p#signupparagraph {
margin-top: 1.5em;
}
.btn:hover {
background-color: #2980B9;
}
.login-link {
font-size: 12px;
color: #444;
display: block;
margin-top: 12px;
}
#cutsiegif{
width:100%;
height:90%;
}
#logout{
margin-top: 25px;
left:50%;
}
#error{
font-size:16px;
color: red;
}
.weatherimg{
margin-top: 10px;
width: 50px;
height: 50px;
}
/* How to make it better - https://sarahleejane.github.io/learning/python/2015/08/09/simple-tables-in-webapps-using-flask-and-pandas-with-python.html */
#gradestable{
font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;
border-bottom: 2px solid #eee;
background-color: white;
margin: auto;
width: 50%;
}
.tableheader{
background-color: #add8e6;
color: white;
border-bottom: 2px solid #eee;
}
.graderow{
font-size: 2.2em;
padding: 10px;
margin-bottom: 40px;
background-color:rgba(229, 231, 238, 0.082);
color: black;
}

BIN
src/static/temp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,23 @@
<head>
<style>
a {
color: red;
padding-top: 150px;
font-size: 13px;
}
</style>
</head>
<body bgcolor=#fff>
<br><br>
<<center>
<font face = "Halvetica", color = "#7b00d4", size = 7>
<div>
Zalogowano pomyslnie!
</div>
</body>

View File

@@ -0,0 +1,25 @@
<head>
<style>
a {
color: red;
padding-top: 150px;
font-size: 13px;
}
</style>
</head>
<body bgcolor=#fff>
<br><br>
<<center>
<font face = "Halvetica", color = "#7b00d4", size = 7>
<div>
Zalogowano pomyslnie!
</div>
<a href = "\wyloguj"> Wyloguj </a>
</body>

View File

@@ -0,0 +1,23 @@
<head>
<style>
a {
color: red;
padding-top: 150px;
font-size: 13px;
}
</style>
</head>
<body bgcolor=#fff>
<br><br>
<<center>
<font face = "Halvetica", color = "#7b00d4", size = 7>
<div>
Zalogowano pomyslnie!
</div>
</body>

23
src/templates/home.html Normal file
View File

@@ -0,0 +1,23 @@
<head>
<style>
a {
color: red;
padding-top: 150px;
font-size: 13px;
}
</style>
</head>
<body bgcolor=#fff>
<br><br>
<<center>
<font face = "Halvetica", color = "#7b00d4", size = 7>
<div>
Zalogowano pomyslnie!
</div>
</body>

View File

@@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/static/style.css" type="text/css">
<title>Login</title>
</head>
<body>
<form action="/login" method="POST">
<div class="login">
<div class="login-screen">
<div class="app-title">
<h1>Login</h1>
</div>
<div class="login-form">
<div class="control-group">
<input type="text" class="login-field" value="" placeholder="username" name="username">
<label class="login-field-icon fui-user" for="login-name"></label>
</div>
<div class="control-group">
<input type="password" class="login-field" value="" placeholder="password" name="password">
<label class="login-field-icon fui-lock" for="login-pass"></label>
</div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul id="error" class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<input type="submit" value="Log in" class="btn btn-primary btn-large btn-block">
<p id="signupparagraph">
You don't have an account? <a href="/signup">Signup</a>
</p>
</div>
</div>
</div>
</form>
</body>
</html>

31
src/templates/pogoda.html Normal file
View File

@@ -0,0 +1,31 @@
<html>
<link rel="stylesheet" href="/static/style.css" type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<!-- Wiecej o bootrapie na w3c school -->
<!-- Aby bootstrap w podstawowej formie dzialal musicie miec: DIV ID ROW, w srodku ktorego macie
DIV ID col-sm-X gdzie x to szerokosc gdzie 12 to 100% strony (mozna podzielic strone na 12 rownych czesci robiac col-sm-1 albo na 2 czesci robiac col-sm-6) -->
<body>
<div id="pogoda">
<div class="container">
<div class="row">
<div id="weathertype">Weather: {{ weathertype }} </div>
<div class="col-sm-2">
<img src="/static/temp.png" class="weatherimg" id="tempimg">
<div id="temp">{{ temp }} Degrees Celcius</div>
</div>
<div class="col-sm-2">
<img src="/static/humid.png" class="weatherimg" id="humidimg">
<div id="humid">Humidity: {{ humid }} </div>
</div>
<div class="col-sm-2">
<img src="/static/rain.png" class="weatherimg" id="rainimg">
<div id="rain"> {{ rain }}</div>
</div>
</div>
</div>
</div>
</body>
</html>

22
src/templates/signup.html Normal file
View File

@@ -0,0 +1,22 @@
<link rel="stylesheet" href="/static/style.css" type="text/css"> {% block body %}
<form action="/register" method="POST">
<div class="login">
<div class="login-screen">
<div class="app-title">
<h1>Register</h1>
</div>
<div class="register-form">
<div class="control-group">
<input type="text" class="login-field" value="" placeholder="username" name="username">
<label class="login-field-icon fui-user" for="login-name"></label>
</div>
<div class="control-group">
<input type="password" class="login-field" value="" placeholder="password" name="password">
<label class="login-field-icon fui-lock" for="login-pass"></label>
</div>
<input type="submit" value="Register" class="btn btn-primary btn-large btn-block">
</div>
</div>
</div>
</form>
{% endblock%}

26
src/weather_api.py Normal file
View File

@@ -0,0 +1,26 @@
import requests
import json
def decode_weather(weather):
weather_from_json = json.loads(weather)
temp = weather_from_json["main"]["temp"]
humidity = weather_from_json["main"]["humidity"]
type = weather_from_json["weather"][0]["main"]
rain = "RAIN" if type == "rain" else "NO RAIN"
return temp, humidity, type, rain
def get_weather():
weather_request = requests.get(
"http://samples.openweathermap.org/data/2.5/weather?q=Warsaw,pl&units=metric"
)
# Czyszczenie odpowiedzi...
weather = weather_request.content.strip()
temp, humidity, type, rain = decode_weather(weather)
return temp, humidity, type, rain