Compare commits
4 commits
9a33ae0923
...
8e0dca0207
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e0dca0207 | |||
| e892a11052 | |||
| 968588eea1 | |||
| 37d30ee29f |
3
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
* text=auto eol=lf
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
22
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12"
|
||||||
|
- run: pip install ruff==0.14.0 -r requirements.txt
|
||||||
|
- name: Ruff (синтаксис и ошибки)
|
||||||
|
run: ruff check --select E9,F .
|
||||||
|
- name: Приложения импортируются
|
||||||
|
run: |
|
||||||
|
cd 01-flask-html && python -c "import server" && cd ..
|
||||||
|
cd 02-flask-wtf-forms && python -c "import server"
|
||||||
|
|
@ -1,273 +1,273 @@
|
||||||
from flask import Flask, url_for, request
|
from flask import Flask, url_for, request
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return "Миссия Колонизация Марса"
|
return "Миссия Колонизация Марса"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/index')
|
@app.route('/index')
|
||||||
def gimn():
|
def gimn():
|
||||||
return 'И на Марсе будут яблони цвести!'
|
return 'И на Марсе будут яблони цвести!'
|
||||||
|
|
||||||
|
|
||||||
@app.route('/promotion')
|
@app.route('/promotion')
|
||||||
def promo():
|
def promo():
|
||||||
return '</br>'.join(['Человечество вырастает из детства.',
|
return '</br>'.join(['Человечество вырастает из детства.',
|
||||||
'Человечеству мала одна планета.',
|
'Человечеству мала одна планета.',
|
||||||
'Мы сделаем обитаемыми безжизненные пока планеты.',
|
'Мы сделаем обитаемыми безжизненные пока планеты.',
|
||||||
'И начнем с Марса!', 'Присоединяйся!'])
|
'И начнем с Марса!', 'Присоединяйся!'])
|
||||||
|
|
||||||
|
|
||||||
@app.route('/image_mars')
|
@app.route('/image_mars')
|
||||||
def img():
|
def img():
|
||||||
return f"""<!doctype html>
|
return f"""<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Привет, Марс!</title>
|
<title>Привет, Марс!</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Жди нас, Марс!</h1>
|
<h1>Жди нас, Марс!</h1>
|
||||||
<img src="{url_for('static', filename='img/planet.jpg')}"></br>
|
<img src="{url_for('static', filename='img/planet.jpg')}"></br>
|
||||||
<a>Вот она какая, красная планета.</a>
|
<a>Вот она какая, красная планета.</a>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
@app.route('/promotion_image')
|
@app.route('/promotion_image')
|
||||||
def promo_img():
|
def promo_img():
|
||||||
return f"""<!doctype html>
|
return f"""<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Колонизация</title>
|
<title>Колонизация</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 class="red" >Жди нас, Марс!</h1>
|
<h1 class="red" >Жди нас, Марс!</h1>
|
||||||
<img src="{url_for('static', filename='img/planet.jpg')}"></br>
|
<img src="{url_for('static', filename='img/planet.jpg')}"></br>
|
||||||
<div class="font black"><b>Человечество вырастает из детства.</b></div></br>
|
<div class="font black"><b>Человечество вырастает из детства.</b></div></br>
|
||||||
<div class="font green"><b>Человечеству мала одна планета.</b></div></br>
|
<div class="font green"><b>Человечеству мала одна планета.</b></div></br>
|
||||||
<div class="font gray"><b>Мы сделаем обитаемыми безжизненные пока планеты.</b></div></br>
|
<div class="font gray"><b>Мы сделаем обитаемыми безжизненные пока планеты.</b></div></br>
|
||||||
<div class="font yellow"><b>И начнем с Марса!</b></div></br>
|
<div class="font yellow"><b>И начнем с Марса!</b></div></br>
|
||||||
<div class="font red"><b>Присоединяйся!</b></div>
|
<div class="font red"><b>Присоединяйся!</b></div>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
@app.route('/astronaut_selection', methods=['POST', 'GET'])
|
@app.route('/astronaut_selection', methods=['POST', 'GET'])
|
||||||
def form_sample():
|
def form_sample():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return f'''<!doctype html>
|
return f'''<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
||||||
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
||||||
crossorigin="anonymous">
|
crossorigin="anonymous">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Отбор астронавтов</title>
|
<title>Отбор астронавтов</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 style="text-align:center">Анкета претендента</h1>
|
<h1 style="text-align:center">Анкета претендента</h1>
|
||||||
<h2 style="text-align:center">на участие в миссии</h2>
|
<h2 style="text-align:center">на участие в миссии</h2>
|
||||||
<div>
|
<div>
|
||||||
<form class="login_form" method="post">
|
<form class="login_form" method="post">
|
||||||
<input type="text" class="form-control" id="text" placeholder="Введите фамилию" name="text1">
|
<input type="text" class="form-control" id="text" placeholder="Введите фамилию" name="text1">
|
||||||
<input type="text" class="form-control" id="text" placeholder="Введите имя" name="text2"></br>
|
<input type="text" class="form-control" id="text" placeholder="Введите имя" name="text2"></br>
|
||||||
<input type="email" class="form-control" id="email" aria-describedby="emailHelp" placeholder="Введите адрес почты" name="email">
|
<input type="email" class="form-control" id="email" aria-describedby="emailHelp" placeholder="Введите адрес почты" name="email">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="classSelect">Какое у Вас образование?</label>
|
<label for="classSelect">Какое у Вас образование?</label>
|
||||||
<select class="form-control" id="classSelect" name="class">
|
<select class="form-control" id="classSelect" name="class">
|
||||||
<option>Начальное</option>
|
<option>Начальное</option>
|
||||||
<option>Среднее оконченное</option>
|
<option>Среднее оконченное</option>
|
||||||
<option>Среднее неоконченное</option>
|
<option>Среднее неоконченное</option>
|
||||||
<option>Высшее оконченное</option>
|
<option>Высшее оконченное</option>
|
||||||
<option>Высшее неоконченное</option>
|
<option>Высшее неоконченное</option>
|
||||||
</select>
|
</select>
|
||||||
</div></br>
|
</div></br>
|
||||||
<label for="classSelect">Какие у Вас есть профессии?</label>
|
<label for="classSelect">Какие у Вас есть профессии?</label>
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept1">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept1">
|
||||||
<label class="form-check-label" for="acceptRules">Инженер-исследователь</label></br>
|
<label class="form-check-label" for="acceptRules">Инженер-исследователь</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept2">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept2">
|
||||||
<label class="form-check-label" for="acceptRules">Инженер-строитель</label></br>
|
<label class="form-check-label" for="acceptRules">Инженер-строитель</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept3">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept3">
|
||||||
<label class="form-check-label" for="acceptRules">Пилот</label></br>
|
<label class="form-check-label" for="acceptRules">Пилот</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept4">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept4">
|
||||||
<label class="form-check-label" for="acceptRules">Метеоролог</label></br>
|
<label class="form-check-label" for="acceptRules">Метеоролог</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept5">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept5">
|
||||||
<label class="form-check-label" for="acceptRules">Инженер по жизнеобеспечению</label></br>
|
<label class="form-check-label" for="acceptRules">Инженер по жизнеобеспечению</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept6">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept6">
|
||||||
<label class="form-check-label" for="acceptRules">Инженер по радиационной защите</label></br>
|
<label class="form-check-label" for="acceptRules">Инженер по радиационной защите</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept7">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept7">
|
||||||
<label class="form-check-label" for="acceptRules">Врач</label></br>
|
<label class="form-check-label" for="acceptRules">Врач</label></br>
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept8">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept8">
|
||||||
<label class="form-check-label" for="acceptRules">Экзобиолог</label></br>
|
<label class="form-check-label" for="acceptRules">Экзобиолог</label></br>
|
||||||
</div></br>
|
</div></br>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="form-check">Укажите пол</label>
|
<label for="form-check">Укажите пол</label>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="radio" name="sex" id="male" value="male">
|
<input class="form-check-input" type="radio" name="sex" id="male" value="male">
|
||||||
<label class="form-check-label" for="male">
|
<label class="form-check-label" for="male">
|
||||||
Мужской
|
Мужской
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<input class="form-check-input" type="radio" name="sex" id="female" value="female">
|
<input class="form-check-input" type="radio" name="sex" id="female" value="female">
|
||||||
<label class="form-check-label" for="female">
|
<label class="form-check-label" for="female">
|
||||||
Женский
|
Женский
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div></br>
|
</div></br>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="about">Почему Вы хотите принять участие в миссии?</label>
|
<label for="about">Почему Вы хотите принять участие в миссии?</label>
|
||||||
<textarea class="form-control" id="about" rows="3" name="about"></textarea>
|
<textarea class="form-control" id="about" rows="3" name="about"></textarea>
|
||||||
</div></br>
|
</div></br>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="photo">Приложите фотографию</label></br>
|
<label for="photo">Приложите фотографию</label></br>
|
||||||
<input type="file" class="form-control-file" id="photo" name="file">
|
<input type="file" class="form-control-file" id="photo" name="file">
|
||||||
</div></br>
|
</div></br>
|
||||||
<div class="form-group form-check">
|
<div class="form-group form-check">
|
||||||
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept">
|
<input type="checkbox" class="form-check-input" id="acceptRules" name="accept">
|
||||||
<label class="form-check-label" for="acceptRules">Готовы остаться на Марсе?</label>
|
<label class="form-check-label" for="acceptRules">Готовы остаться на Марсе?</label>
|
||||||
</div></br>
|
</div></br>
|
||||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>'''
|
</html>'''
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
print("Фамилия -", request.form.get('text1'))
|
print("Фамилия -", request.form.get('text1'))
|
||||||
print("Имя -", request.form.get('text2'))
|
print("Имя -", request.form.get('text2'))
|
||||||
print("Почта -", request.form.get('email'))
|
print("Почта -", request.form.get('email'))
|
||||||
print("Образование -", request.form.get('class'))
|
print("Образование -", request.form.get('class'))
|
||||||
prof = []
|
prof = []
|
||||||
typis = {'accept1': "Инженер-исследователь", 'accept2': "Инженер-строитель", 'accept3': "Пилот",
|
typis = {'accept1': "Инженер-исследователь", 'accept2': "Инженер-строитель", 'accept3': "Пилот",
|
||||||
'accept4': "Метеоролог", 'accept5': 'Инженер по жизнеобеспечению',
|
'accept4': "Метеоролог", 'accept5': 'Инженер по жизнеобеспечению',
|
||||||
'accept6': 'Инженер по радиационной защите', 'accept7': "Врач", 'accept8': "Экзобиолог"}
|
'accept6': 'Инженер по радиационной защите', 'accept7': "Врач", 'accept8': "Экзобиолог"}
|
||||||
for i in typis:
|
for i in typis:
|
||||||
a = request.form.get(i)
|
a = request.form.get(i)
|
||||||
if a:
|
if a:
|
||||||
prof.append(typis[i])
|
prof.append(typis[i])
|
||||||
print("Профкссия(-и):", ", ".join(prof))
|
print("Профкссия(-и):", ", ".join(prof))
|
||||||
print("Пол -", request.form.get('sex'))
|
print("Пол -", request.form.get('sex'))
|
||||||
print("Причины участия -", request.form.get('about'))
|
print("Причины участия -", request.form.get('about'))
|
||||||
print("Фото -", request.form.get('file'))
|
print("Фото -", request.form.get('file'))
|
||||||
if request.form.get('accept'):
|
if request.form.get('accept'):
|
||||||
print("Подписан на программу")
|
print("Подписан на программу")
|
||||||
else:
|
else:
|
||||||
print("Отказался от программы")
|
print("Отказался от программы")
|
||||||
return "Форма отправлена"
|
return "Форма отправлена"
|
||||||
|
|
||||||
|
|
||||||
@app.route('/choice/<planet_name>')
|
@app.route('/choice/<planet_name>')
|
||||||
def choice(planet_name):
|
def choice(planet_name):
|
||||||
return f"""<!doctype html>
|
return f"""<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Колонизация</title>
|
<title>Колонизация</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 class="font">Моё предложение: {planet_name}</h1>
|
<h1 class="font">Моё предложение: {planet_name}</h1>
|
||||||
<h1>Эта планета близка к Земле;</h1>
|
<h1>Эта планета близка к Земле;</h1>
|
||||||
<div class="font green"><b>На ней много необходимых ресурсов;</b></div></br>
|
<div class="font green"><b>На ней много необходимых ресурсов;</b></div></br>
|
||||||
<div class="font gray"><b>На ней есть вода и атмосфера;</b></div></br>
|
<div class="font gray"><b>На ней есть вода и атмосфера;</b></div></br>
|
||||||
<div class="font yellow"><b>На ней есть небольшое магнитное поле;</b></div></br>
|
<div class="font yellow"><b>На ней есть небольшое магнитное поле;</b></div></br>
|
||||||
<div class="font red"><b>Наконец, она просто красива!</b></div></br>
|
<div class="font red"><b>Наконец, она просто красива!</b></div></br>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
@app.route('/results/<nickname>/<int:level>/<float:rating>')
|
@app.route('/results/<nickname>/<int:level>/<float:rating>')
|
||||||
def result(nickname, level, rating):
|
def result(nickname, level, rating):
|
||||||
return f"""<!doctype html>
|
return f"""<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Колонизация</title>
|
<title>Колонизация</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 class="font">Результаты отбора</h1>
|
<h1 class="font">Результаты отбора</h1>
|
||||||
<h1>Претендента на участие в миссии {nickname}:</h1>
|
<h1>Претендента на участие в миссии {nickname}:</h1>
|
||||||
<div class="font green"><b>Поздравляем! Ваш рейтинг после {level} этапа отбора</b></div>
|
<div class="font green"><b>Поздравляем! Ваш рейтинг после {level} этапа отбора</b></div>
|
||||||
<h1>составляет {rating}!</h1>
|
<h1>составляет {rating}!</h1>
|
||||||
<div class="font yellow"><b>Желаем удачи!</b></div></br>
|
<div class="font yellow"><b>Желаем удачи!</b></div></br>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
||||||
@app.route('/load_photo', methods=['POST', 'GET'])
|
@app.route('/load_photo', methods=['POST', 'GET'])
|
||||||
def photo():
|
def photo():
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return f'''<!doctype html>
|
return f'''<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
||||||
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
||||||
crossorigin="anonymous">
|
crossorigin="anonymous">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Отбор астронавтов</title>
|
<title>Отбор астронавтов</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 style="text-align:center">Загрузка фотографии</h1>
|
<h1 style="text-align:center">Загрузка фотографии</h1>
|
||||||
<h2 style="text-align:center">для участия в миссии</h2>
|
<h2 style="text-align:center">для участия в миссии</h2>
|
||||||
<div>
|
<div>
|
||||||
<form class="login_form" method="post" enctype="multipart/form-data">
|
<form class="login_form" method="post" enctype="multipart/form-data">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="photo">Приложите фотографию</label></br>
|
<label for="photo">Приложите фотографию</label></br>
|
||||||
<input type="file" class="form-control-file" id="photo" name="file">
|
<input type="file" class="form-control-file" id="photo" name="file">
|
||||||
</div></br>
|
</div></br>
|
||||||
<img class="width" src="{url_for('static', filename='img/img.png')}"></br>
|
<img class="width" src="{url_for('static', filename='img/img.png')}"></br>
|
||||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>'''
|
</html>'''
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
f = request.files['file']
|
f = request.files['file']
|
||||||
if f:
|
if f:
|
||||||
with open("static/img/img.png", "wb") as file:
|
with open("static/img/img.png", "wb") as file:
|
||||||
file.write(f.read())
|
file.write(f.read())
|
||||||
return f'''<!doctype html>
|
return f'''<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
|
||||||
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
|
||||||
crossorigin="anonymous">
|
crossorigin="anonymous">
|
||||||
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
<link rel="stylesheet" type="text/css" href="{url_for('static', filename='css/style.css')}" />
|
||||||
<title>Отбор астронавтов</title>
|
<title>Отбор астронавтов</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1 style="text-align:center">Загрузка фотографии</h1>
|
<h1 style="text-align:center">Загрузка фотографии</h1>
|
||||||
<h2 style="text-align:center">для участия в миссии</h2>
|
<h2 style="text-align:center">для участия в миссии</h2>
|
||||||
<div>
|
<div>
|
||||||
<form class="login_form" method="post" enctype="multipart/form-data">
|
<form class="login_form" method="post" enctype="multipart/form-data">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="photo">Приложите фотографию</label></br>
|
<label for="photo">Приложите фотографию</label></br>
|
||||||
<input type="file" class="form-control-file" id="photo" name="file">
|
<input type="file" class="form-control-file" id="photo" name="file">
|
||||||
</div></br>
|
</div></br>
|
||||||
<img class="width" src="{url_for('static', filename='img/img.png')}"></br>
|
<img class="width" src="{url_for('static', filename='img/img.png')}"></br>
|
||||||
<button type="submit" class="btn btn-primary">Отправить</button>
|
<button type="submit" class="btn btn-primary">Отправить</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>'''
|
</html>'''
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(port=8080, host='127.0.0.1')
|
app.run(port=8080, host='127.0.0.1')
|
||||||
|
|
@ -1,54 +1,54 @@
|
||||||
h1.red {
|
h1.red {
|
||||||
color: #d22e3a;
|
color: #d22e3a;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1.font {
|
h1.font {
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
img.width {
|
img.width {
|
||||||
width: 430px;
|
width: 430px;
|
||||||
}
|
}
|
||||||
|
|
||||||
form.login_form {
|
form.login_form {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
max-width: 450px;
|
max-width: 450px;
|
||||||
background-color: #ffdcbb;
|
background-color: #ffdcbb;
|
||||||
border: 1px solid gray;
|
border: 1px solid gray;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.font {
|
div.font {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
width: 600px;
|
width: 600px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.red {
|
div.red {
|
||||||
color: #6b1c29;
|
color: #6b1c29;
|
||||||
background-color: #f7d7dc;
|
background-color: #f7d7dc;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.black {
|
div.black {
|
||||||
color: #000000;
|
color: #000000;
|
||||||
background-color: #d6d9d9;
|
background-color: #d6d9d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.green {
|
div.green {
|
||||||
color: #185921;
|
color: #185921;
|
||||||
background-color: #d3eedc;
|
background-color: #d3eedc;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.gray {
|
div.gray {
|
||||||
color: #393c42;
|
color: #393c42;
|
||||||
background-color: #e1e3e4;
|
background-color: #e1e3e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.yellow {
|
div.yellow {
|
||||||
color: #845900;
|
color: #845900;
|
||||||
background-color: #fff3ce;
|
background-color: #fff3ce;
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 422 KiB After Width: | Height: | Size: 422 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
|
@ -1,14 +1,14 @@
|
||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from wtforms import StringField, PasswordField, BooleanField, SubmitField
|
from wtforms import StringField, PasswordField, SubmitField
|
||||||
from wtforms.validators import DataRequired
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(FlaskForm):
|
class LoginForm(FlaskForm):
|
||||||
id_user = StringField('Id астронавта', validators=[DataRequired()])
|
id_user = StringField('Id астронавта', validators=[DataRequired()])
|
||||||
pas_user = PasswordField('Пароль астронавта', validators=[DataRequired()])
|
pas_user = PasswordField('Пароль астронавта', validators=[DataRequired()])
|
||||||
id_cap = StringField('Id капитана', validators=[DataRequired()])
|
id_cap = StringField('Id капитана', validators=[DataRequired()])
|
||||||
pas_cap = PasswordField('Пароль капитана', validators=[DataRequired()])
|
pas_cap = PasswordField('Пароль капитана', validators=[DataRequired()])
|
||||||
# remember_me = BooleanField('Запомнить меня') <p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
|
# remember_me = BooleanField('Запомнить меня') <p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
|
||||||
submit = SubmitField('Доступ')
|
submit = SubmitField('Доступ')
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
{
|
{
|
||||||
"news": [
|
"news": [
|
||||||
{
|
{
|
||||||
"title": "Сегодня хорошая погода",
|
"title": "Сегодня хорошая погода",
|
||||||
"content": "Невероятно, сегодня хорошая погода"
|
"content": "Невероятно, сегодня хорошая погода"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Завтра хорошая погода",
|
"title": "Завтра хорошая погода",
|
||||||
"content": "С ума сойти, и завтра хорошая погода"
|
"content": "С ума сойти, и завтра хорошая погода"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": "Послезавтра дождь",
|
"title": "Послезавтра дождь",
|
||||||
"content": "Все вошло в норму"
|
"content": "Все вошло в норму"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -1,53 +1,55 @@
|
||||||
from flask import Flask, render_template, redirect
|
import os
|
||||||
from loginform import LoginForm
|
|
||||||
|
from flask import Flask, render_template, redirect
|
||||||
|
from loginform import LoginForm
|
||||||
app = Flask(__name__)
|
|
||||||
app.config['SECRET_KEY'] = 'yandexlyceum_secret_key'
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'yandexlyceum_secret_key')
|
||||||
@app.route('/<label>')
|
|
||||||
@app.route('/index/<label>')
|
|
||||||
def index(label):
|
@app.route('/<label>')
|
||||||
param = {'label': 'И на Марсе будут яблони цвести!', 'title': label}
|
@app.route('/index/<label>')
|
||||||
return render_template('index.html', **param)
|
def index(label):
|
||||||
|
param = {'label': 'И на Марсе будут яблони цвести!', 'title': label}
|
||||||
|
return render_template('index.html', **param)
|
||||||
@app.route('/training/<prof>')
|
|
||||||
def training(prof):
|
|
||||||
param = {'title': "Тренировки в полёте", "spec": prof}
|
@app.route('/training/<prof>')
|
||||||
return render_template('training.html', **param)
|
def training(prof):
|
||||||
|
param = {'title': "Тренировки в полёте", "spec": prof}
|
||||||
|
return render_template('training.html', **param)
|
||||||
@app.route('/list_prof/<var>')
|
|
||||||
def list_prof(var):
|
|
||||||
param = {'title': "Список профессий", "var": var}
|
@app.route('/list_prof/<var>')
|
||||||
return render_template('list_prof.html', **param)
|
def list_prof(var):
|
||||||
|
param = {'title': "Список профессий", "var": var}
|
||||||
|
return render_template('list_prof.html', **param)
|
||||||
@app.route('/answer')
|
|
||||||
@app.route('/auto_answer')
|
|
||||||
def answer():
|
@app.route('/answer')
|
||||||
param = {'title': "Анкета", 'surname': "Фёдоров", 'name': "Марк", 'education': "Среднее", 'profession': " Писатель",
|
@app.route('/auto_answer')
|
||||||
'sex': "Male", 'motivation': "Распространить хип-хоп в космос!", 'ready': "True"}
|
def answer():
|
||||||
return render_template('auto_answer.html', **param)
|
param = {'title': "Анкета", 'surname': "Фёдоров", 'name': "Марк", 'education': "Среднее", 'profession': " Писатель",
|
||||||
|
'sex': "Male", 'motivation': "Распространить хип-хоп в космос!", 'ready': "True"}
|
||||||
|
return render_template('auto_answer.html', **param)
|
||||||
@app.route('/login', methods=['GET', 'POST'])
|
|
||||||
def login():
|
|
||||||
param = {'title': "Аварийный доступ"}
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
form = LoginForm()
|
def login():
|
||||||
if form.validate_on_submit():
|
param = {'title': "Аварийный доступ"}
|
||||||
return redirect('/success')
|
form = LoginForm()
|
||||||
return render_template('login.html', **param, form=form)
|
if form.validate_on_submit():
|
||||||
|
return redirect('/success')
|
||||||
|
return render_template('login.html', **param, form=form)
|
||||||
@app.route('/distribution')
|
|
||||||
def success():
|
|
||||||
param = {'title': "По каютам!", "users": ['Ридли Скотт', 'Энди Уир', 'Марк Уотни', "Венката Капур",
|
@app.route('/distribution')
|
||||||
'Тедди Сандерс', 'Шон Бин']}
|
def success():
|
||||||
return render_template('distribution.html', **param)
|
param = {'title': "По каютам!", "users": ['Ридли Скотт', 'Энди Уир', 'Марк Уотни', "Венката Капур",
|
||||||
|
'Тедди Сандерс', 'Шон Бин']}
|
||||||
|
return render_template('distribution.html', **param)
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(port=8080, host='127.0.0.1')
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(port=8080, host='127.0.0.1')
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
h4.color_edit {
|
h4.color_edit {
|
||||||
color: "black";
|
color: "black";
|
||||||
}
|
}
|
||||||
|
|
||||||
p.padmarging {
|
p.padmarging {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 268 KiB After Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 267 KiB After Width: | Height: | Size: 267 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
|
@ -1,15 +1,15 @@
|
||||||
{% extends "base_two.html" %}
|
{% extends "base_two.html" %}
|
||||||
|
|
||||||
{% block content1 %}
|
{% block content1 %}
|
||||||
<div class="alert alert-light" role="alert">
|
<div class="alert alert-light" role="alert">
|
||||||
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Фамилия: {{surname}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Фамилия: {{surname}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Имя: {{name}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Имя: {{name}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Образование: {{education}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Образование: {{education}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Профессия: {{profession}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Профессия: {{profession}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Пол: {{sex}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Пол: {{sex}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Мотивация: {{motivation}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Мотивация: {{motivation}}</p></h4>
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Готовы остаться на Марсе? {{ready}}</p></h4>
|
<h4 class="color_edit"><p style="padding-left: 60px">Готовы остаться на Марсе? {{ready}}</p></h4>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,32 +1,32 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<!-- Required meta tags -->
|
<!-- Required meta tags -->
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
<!-- Bootstrap CSS -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
||||||
rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
|
rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
|
||||||
crossorigin="anonymous">
|
crossorigin="anonymous">
|
||||||
|
|
||||||
<!-- <link rel="stylesheet" type="text/css" href="static/css/style.css" /> -->
|
<!-- <link rel="stylesheet" type="text/css" href="static/css/style.css" /> -->
|
||||||
<title>{{title}}</title>
|
<title>{{title}}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<nav class="navbar navbar-light bg-light">
|
<nav class="navbar navbar-light bg-light">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand mb-0" href="#"><h1>Миссия Колонизация Марса</h1></a>
|
<a class="navbar-brand mb-0" href="#"><h1>Миссия Колонизация Марса</h1></a>
|
||||||
<div class="navbar-text mb-0 h5">
|
<div class="navbar-text mb-0 h5">
|
||||||
Mars One
|
Mars One
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
<!-- Begin page content -->
|
<!-- Begin page content -->
|
||||||
<main role="main" class="container-fluid">
|
<main role="main" class="container-fluid">
|
||||||
{% block content1 %}{% endblock %}
|
{% block content1 %}{% endblock %}
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content1 %}
|
{% block content1 %}
|
||||||
<div class="alert alert-light" role="alert">
|
<div class="alert alert-light" role="alert">
|
||||||
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% block content2 %}{% endblock %}
|
{% block content2 %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
{% extends "base_two.html" %}
|
{% extends "base_two.html" %}
|
||||||
|
|
||||||
{% block content2 %}
|
{% block content2 %}
|
||||||
<h1 align="center">Размещение по каютам</h1>
|
<h1 align="center">Размещение по каютам</h1>
|
||||||
{% for user in users %}
|
{% for user in users %}
|
||||||
<h3>{{ user }} - Каюта № {{ loop.index }} {% if loop.first %} - первый в очереди {% endif %}</h3>
|
<h3>{{ user }} - Каюта № {{ loop.index }} {% if loop.first %} - первый в очереди {% endif %}</h3>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content1 %}
|
{% block content1 %}
|
||||||
<h4>{{label}}</h4>
|
<h4>{{label}}</h4>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,27 +1,27 @@
|
||||||
{% extends "base_two.html" %}
|
{% extends "base_two.html" %}
|
||||||
|
|
||||||
{% block content2 %}
|
{% block content2 %}
|
||||||
{% set all_prof = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог",
|
{% set all_prof = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог",
|
||||||
'инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
'инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
||||||
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
||||||
"киберинженер", "штурман", "пилот дронов"] %}
|
"киберинженер", "штурман", "пилот дронов"] %}
|
||||||
{% if var == "ol" %}
|
{% if var == "ol" %}
|
||||||
<p class="h1">Список профессий</p>
|
<p class="h1">Список профессий</p>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<ol>
|
<ol>
|
||||||
{% for p in all_prof %}
|
{% for p in all_prof %}
|
||||||
<li class="h5">{{p}}</li>
|
<li class="h5">{{p}}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
{% elif var == "ul" %}
|
{% elif var == "ul" %}
|
||||||
<p class="h1">Список профессий</p>
|
<p class="h1">Список профессий</p>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% for p in all_prof %}
|
{% for p in all_prof %}
|
||||||
<li class="h5">{{p}}</li>
|
<li class="h5">{{p}}</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="h1">Индекс указан неправильно!</p>
|
<p class="h1">Индекс указан неправильно!</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,45 +1,45 @@
|
||||||
{% extends "base_two.html" %}
|
{% extends "base_two.html" %}
|
||||||
|
|
||||||
{% block content2 %}
|
{% block content2 %}
|
||||||
<h1><img src="../static/img/mars_ico.png">Аварийный доступ</h1><br>
|
<h1><img src="../static/img/mars_ico.png">Аварийный доступ</h1><br>
|
||||||
<form action="" method="post" novalidate>
|
<form action="" method="post" novalidate>
|
||||||
{{ form.hidden_tag() }}
|
{{ form.hidden_tag() }}
|
||||||
<p>
|
<p>
|
||||||
<big>{{ form.id_user.label }}</big>><br>
|
<big>{{ form.id_user.label }}</big>><br>
|
||||||
{{ form.id_user(class="form-control") }}<br>
|
{{ form.id_user(class="form-control") }}<br>
|
||||||
{% for error in form.id_user.errors %}
|
{% for error in form.id_user.errors %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<big>{{ form.pas_user.label }}</big><br>
|
<big>{{ form.pas_user.label }}</big><br>
|
||||||
{{ form.pas_user(class="form-control", type="password") }}<br>
|
{{ form.pas_user(class="form-control", type="password") }}<br>
|
||||||
{% for error in form.pas_user.errors %}
|
{% for error in form.pas_user.errors %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<big>{{ form.id_cap.label }}</big><br>
|
<big>{{ form.id_cap.label }}</big><br>
|
||||||
{{ form.id_cap(class="form-control") }}<br>
|
{{ form.id_cap(class="form-control") }}<br>
|
||||||
{% for error in form.id_cap.errors %}
|
{% for error in form.id_cap.errors %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<big>{{ form.pas_cap.label }}</big><br>
|
<big>{{ form.pas_cap.label }}</big><br>
|
||||||
{{ form.pas_cap(class="form-control", type="password") }}<br>
|
{{ form.pas_cap(class="form-control", type="password") }}<br>
|
||||||
{% for error in form.pas_cap.errors %}
|
{% for error in form.pas_cap.errors %}
|
||||||
<div class="alert alert-danger" role="alert">
|
<div class="alert alert-danger" role="alert">
|
||||||
{{ error }}
|
{{ error }}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</p>
|
</p>
|
||||||
<p>{{ form.submit(type="submit", class="btn btn-primary") }}</p>
|
<p>{{ form.submit(type="submit", class="btn btn-primary") }}</p>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,17 +1,17 @@
|
||||||
{% extends "base_two.html" %}
|
{% extends "base_two.html" %}
|
||||||
|
|
||||||
{% block content2 %}
|
{% block content2 %}
|
||||||
{% set sin = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог"] %}
|
{% set sin = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог"] %}
|
||||||
{% set inj = ['инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
{% set inj = ['инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
||||||
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
||||||
"киберинженер", "штурман", "пилот дронов"] %}
|
"киберинженер", "штурман", "пилот дронов"] %}
|
||||||
{% if spec.lower() in sin %}
|
{% if spec.lower() in sin %}
|
||||||
<p class="text-center h2">Научные симуляторы</p>
|
<p class="text-center h2">Научные симуляторы</p>
|
||||||
<p class="text-center"><img src="/static/img/kb1.jpg" class="img-fluid"></p>
|
<p class="text-center"><img src="/static/img/kb1.jpg" class="img-fluid"></p>
|
||||||
{% elif spec.lower() in inj %}
|
{% elif spec.lower() in inj %}
|
||||||
<p class="text-center h2">Инженерные тренажеры</p>
|
<p class="text-center h2">Инженерные тренажеры</p>
|
||||||
<p class="text-center"><img src="/static/img/kb2.jpg" class="img-fluid"></p>
|
<p class="text-center"><img src="/static/img/kb2.jpg" class="img-fluid"></p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p class="text-center h1">В наших списках ваша профессия отсутствует!</p>
|
<p class="text-center h1">В наших списках ваша профессия отсутствует!</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
@ -1,21 +1,21 @@
|
||||||
def delta(org, adr):
|
def delta(org, adr):
|
||||||
first = "0.0001"
|
first = "0.0001"
|
||||||
adr = list(map(float, adr.split(',')))
|
adr = list(map(float, adr.split(',')))
|
||||||
|
|
||||||
k1 = float(first)
|
k1 = float(first)
|
||||||
while True:
|
while True:
|
||||||
k = adr[0] + k1
|
k = adr[0] + k1
|
||||||
if org[0] + 0.001 >= k:
|
if org[0] + 0.001 >= k:
|
||||||
k1 *= 10
|
k1 *= 10
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
k2 = float(first)
|
k2 = float(first)
|
||||||
while True:
|
while True:
|
||||||
k = adr[1] + k2
|
k = adr[1] + k2
|
||||||
if org[1] + 0.001 >= k:
|
if org[1] + 0.001 >= k:
|
||||||
k2 *= 10
|
k2 *= 10
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
|
||||||
return str(max(k1, k2))
|
return str(max(k1, k2))
|
||||||
|
|
@ -1,45 +1,46 @@
|
||||||
from io import BytesIO
|
import os
|
||||||
from PIL import Image
|
from io import BytesIO
|
||||||
from delta import delta
|
from PIL import Image
|
||||||
import requests
|
from delta import delta
|
||||||
|
import requests
|
||||||
|
|
||||||
search_api_server = "https://search-maps.yandex.ru/v1/"
|
|
||||||
api_key = "your_yandex_api_key_here"
|
search_api_server = "https://search-maps.yandex.ru/v1/"
|
||||||
|
api_key = os.environ.get("YANDEX_API_KEY", "")
|
||||||
address_ll = "37.588392,55.734036"
|
|
||||||
|
address_ll = "37.588392,55.734036"
|
||||||
search_params = {
|
|
||||||
"apikey": api_key,
|
search_params = {
|
||||||
"text": "магазин",
|
"apikey": api_key,
|
||||||
"lang": "ru_RU",
|
"text": "магазин",
|
||||||
"ll": address_ll,
|
"lang": "ru_RU",
|
||||||
"type": "biz"
|
"ll": address_ll,
|
||||||
}
|
"type": "biz"
|
||||||
|
}
|
||||||
response = requests.get(search_api_server, params=search_params)
|
|
||||||
if not response:
|
response = requests.get(search_api_server, params=search_params)
|
||||||
pass
|
if not response:
|
||||||
|
pass
|
||||||
json_response = response.json()
|
|
||||||
|
json_response = response.json()
|
||||||
organization = json_response["features"][0]
|
|
||||||
org_name = organization["properties"]["CompanyMetaData"]["name"]
|
organization = json_response["features"][0]
|
||||||
org_address = organization["properties"]["CompanyMetaData"]["address"]
|
org_name = organization["properties"]["CompanyMetaData"]["name"]
|
||||||
|
org_address = organization["properties"]["CompanyMetaData"]["address"]
|
||||||
point = organization["geometry"]["coordinates"]
|
|
||||||
org_point = "{0},{1}".format(point[0], point[1])
|
point = organization["geometry"]["coordinates"]
|
||||||
delta = delta(point, address_ll)
|
org_point = "{0},{1}".format(point[0], point[1])
|
||||||
|
delta = delta(point, address_ll)
|
||||||
map_params = {
|
|
||||||
"ll": address_ll,
|
map_params = {
|
||||||
"spn": ",".join([delta, delta]),
|
"ll": address_ll,
|
||||||
"l": "map",
|
"spn": ",".join([delta, delta]),
|
||||||
"pt": "{0},pm2dgl".format(org_point)
|
"l": "map",
|
||||||
}
|
"pt": "{0},pm2dgl".format(org_point)
|
||||||
|
}
|
||||||
map_api_server = "http://static-maps.yandex.ru/1.x/"
|
|
||||||
response = requests.get(map_api_server, params=map_params)
|
map_api_server = "http://static-maps.yandex.ru/1.x/"
|
||||||
|
response = requests.get(map_api_server, params=map_params)
|
||||||
Image.open(BytesIO(
|
|
||||||
|
Image.open(BytesIO(
|
||||||
response.content)).show()
|
response.content)).show()
|
||||||
45
README.en.md
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Yandex Lyceum
|
||||||
|
|
||||||
|
[Русский](README.md) · **English**
|
||||||
|
|
||||||
|
[](https://github.com/EDeev/yandex_lyceum/actions/workflows/ci.yml)
|
||||||
|
|
||||||
|
Solutions to the Yandex Lyceum web development course: Flask apps built around the "Mars colonization
|
||||||
|
mission" storyline, plus organization search via the Yandex Maps API.
|
||||||
|
|
||||||
|
**Status:** coursework (Yandex Lyceum, 2022), completed, archived
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Stack:** Python · Flask · Jinja2 · Flask-WTF · Bootstrap · Yandex Maps API · Pillow
|
||||||
|
|
||||||
|
| Folder | Contents |
|
||||||
|
|---|---|
|
||||||
|
| `01-flask-html` | Flask and Jinja2 pages: mission promo page, applicant form, planet choice, selection results, photo upload |
|
||||||
|
| `02-flask-wtf-forms` | Flask-WTF forms: sign-in, training by profession, list of professions, form auto-answer, cabin assignment |
|
||||||
|
| `03-yandex-maps-search` | finding the nearest organization via the Yandex organization search API and showing a map |
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r requirements.txt
|
||||||
|
cd 01-flask-html && python server.py # http://127.0.0.1:8080
|
||||||
|
YANDEX_API_KEY=your_key python 03-yandex-maps-search/main.py
|
||||||
|
```
|
||||||
|
|
||||||
|
`03-yandex-maps-search` needs a Yandex organization search API key in `YANDEX_API_KEY`.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Coursework (Yandex Lyceum, 2021/22). The code is open for study; there is no separate license.
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
**Egor Deev** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<sub>⭐ If you find this project useful, give it a star on GitHub!</sub>
|
||||||
|
<p><sub>Made with ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
|
||||||
|
</div>
|
||||||
140
README.md
|
|
@ -1,139 +1,45 @@
|
||||||
# Yandex Lyceum Projects 🚀
|
# Yandex Lyceum
|
||||||
|
|
||||||
> Коллекция веб-приложений разработанных в рамках образовательной программы Яндекс Лицея
|
**Русский** · [English](README.en.md)
|
||||||
|
|
||||||
## 📋 Описание проекта
|
[](https://github.com/EDeev/yandex_lyceum/actions/workflows/ci.yml)
|
||||||
|
|
||||||
Репозиторий содержит комплекс учебных проектов, демонстрирующих эволюцию навыков веб-разработки от базовых HTML-страниц до полнофункциональных Flask-приложений с интеграцией внешних API.
|
Решения задач курса веб-разработки Яндекс Лицея: Flask-приложения по сюжету «Миссия колонизации Марса»
|
||||||
|
и поиск организаций через API Яндекс.Карт.
|
||||||
|
|
||||||
## 🏗️ Архитектура решений
|
**Статус:** учебный проект (Яндекс Лицей, 2022), завершён, в архиве
|
||||||
|
|
||||||
### Модули проекта:
|

|
||||||
|
|
||||||
#### 1. **WEB.HTML** - Базовая веб-разработка
|
**Стек:** Python · Flask · Jinja2 · Flask-WTF · Bootstrap · API Яндекс.Карт · Pillow
|
||||||
- Статические HTML-страницы с CSS-стилизацией
|
|
||||||
- Обработка форм и файловых загрузок
|
|
||||||
- Маршрутизация и шаблонизация
|
|
||||||
|
|
||||||
#### 2. **WEB.HTML 2** - Продвинутая веб-архитектура
|
| Папка | Что внутри |
|
||||||
- Flask-приложение с расширенной функциональностью
|
|---|---|
|
||||||
- Интеграция Bootstrap для адаптивного дизайна
|
| `01-flask-html` | страницы на Flask и Jinja2: рекламная страница миссии, анкета претендента, выбор планеты, результаты отбора, загрузка фото |
|
||||||
- Система аутентификации и авторизации
|
| `02-flask-wtf-forms` | формы на Flask-WTF: вход, тренажёры по профессиям, список профессий, автоответ анкеты, распределение по каютам |
|
||||||
|
| `03-yandex-maps-search` | поиск ближайшей организации через API поиска по организациям и показ карты |
|
||||||
|
|
||||||
#### 3. **WEB.HTML flask-wtf** - Профессиональные веб-формы
|
## Запуск
|
||||||
- Валидация пользовательского ввода
|
|
||||||
- CSRF-защита
|
|
||||||
- Обработка сложных форм с множественными полями
|
|
||||||
|
|
||||||
#### 4. **Полный поиск** - Геоинформационные сервисы
|
|
||||||
- Интеграция с Yandex Maps API
|
|
||||||
- Алгоритмы геопозиционирования
|
|
||||||
- Динамическое построение карт
|
|
||||||
|
|
||||||
## 🛠️ Технологический стек
|
|
||||||
|
|
||||||
```
|
|
||||||
Backend: Flask 2.0+, Python 3.8+
|
|
||||||
Frontend: HTML5, CSS3, Bootstrap 5.1.3
|
|
||||||
Forms: Flask-WTF, WTForms
|
|
||||||
APIs: Yandex Maps Search API
|
|
||||||
Libraries: Pillow, Requests, Jinja2
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🚀 Быстрый старт
|
|
||||||
|
|
||||||
### Установка зависимостей
|
|
||||||
```bash
|
```bash
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
cd 01-flask-html && python server.py # http://127.0.0.1:8080
|
||||||
|
YANDEX_API_KEY=ваш_ключ python 03-yandex-maps-search/main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
### Запуск приложений
|
Для `03-yandex-maps-search` нужен ключ API поиска по организациям Яндекса в переменной `YANDEX_API_KEY`.
|
||||||
```bash
|
|
||||||
# Базовое HTML-приложение
|
|
||||||
cd "WEB.HTML"
|
|
||||||
python server.py
|
|
||||||
|
|
||||||
# Flask-приложение с шаблонами
|
## Лицензия
|
||||||
cd "WEB.HTML 2"
|
|
||||||
python server.py
|
|
||||||
|
|
||||||
# Приложение с формами
|
Учебный проект (Яндекс Лицей, 2021/22). Код открыт для изучения, отдельной лицензии нет.
|
||||||
cd "WEB.HTML flask-wtf"
|
|
||||||
python server.py
|
|
||||||
```
|
|
||||||
|
|
||||||
### Конфигурация API
|
## Автор
|
||||||
Для работы геосервисов необходимо настроить API-ключ в `main.py`:
|
|
||||||
```python
|
|
||||||
api_key = "your_yandex_api_key_here"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 📁 Структура проекта
|
**Деев Егор Викторович** — [GitHub](https://github.com/EDeev) · [Telegram](https://t.me/DeevEgor) · [egor@deev.space](mailto:egor@deev.space)
|
||||||
|
|
||||||
```
|
|
||||||
yandex_lyceum/
|
|
||||||
├── WEB.HTML/ # Базовые веб-технологии
|
|
||||||
│ ├── server.py # Flask-сервер
|
|
||||||
│ ├── static/ # Статические ресурсы
|
|
||||||
│ └── templates/ # HTML-шаблоны
|
|
||||||
├── WEB.HTML 2/ # Расширенная веб-архитектура
|
|
||||||
│ ├── server.py
|
|
||||||
│ ├── loginform.py # Формы авторизации
|
|
||||||
│ └── templates/
|
|
||||||
├── WEB.HTML flask-wtf/ # Профессиональные формы
|
|
||||||
└── Полный поиск/ # Геоинформационные сервисы
|
|
||||||
├── main.py # Основная логика
|
|
||||||
└── delta.py # Вспомогательные алгоритмы
|
|
||||||
```
|
|
||||||
|
|
||||||
## 🎯 Функциональные возможности
|
|
||||||
|
|
||||||
### Веб-интерфейсы:
|
|
||||||
- **Космическая тематика:** Интерактивные страницы миссии колонизации Марса
|
|
||||||
- **Система профессий:** Каталогизация и фильтрация специальностей
|
|
||||||
- **Анкетирование:** Комплексные формы с валидацией данных
|
|
||||||
- **Аутентификация:** Многоуровневая система доступа
|
|
||||||
|
|
||||||
### Геосервисы:
|
|
||||||
- **Поиск объектов:** Интеграция с Yandex Search API
|
|
||||||
- **Картографирование:** Динамическое построение карт
|
|
||||||
- **Геопозиционирование:** Алгоритмы расчета координат
|
|
||||||
|
|
||||||
## 🔧 Конфигурация
|
|
||||||
|
|
||||||
### Переменные окружения:
|
|
||||||
```bash
|
|
||||||
FLASK_ENV=development
|
|
||||||
SECRET_KEY=yandexlyceum_secret_key
|
|
||||||
YANDEX_API_KEY=your_api_key
|
|
||||||
```
|
|
||||||
|
|
||||||
### Порты по умолчанию:
|
|
||||||
- **Flask-приложения:** `127.0.0.1:8080`
|
|
||||||
- **Статические файлы:** автоматическая маршрутизация
|
|
||||||
|
|
||||||
## 🏆 Образовательные цели
|
|
||||||
|
|
||||||
Проект демонстрирует прогрессивное освоение:
|
|
||||||
- Фундаментальных веб-технологий
|
|
||||||
- Серверной архитектуры Flask
|
|
||||||
- Интеграции внешних API
|
|
||||||
- Профессиональных практик разработки
|
|
||||||
|
|
||||||
## 📄 Лицензия
|
|
||||||
|
|
||||||
Образовательный проект в рамках программы Яндекс Лицея
|
|
||||||
|
|
||||||
## 👨💻 Автор
|
|
||||||
|
|
||||||
**Деев Егор Викторович** - Backend Developer
|
|
||||||
- GitHub: [@EDeev](https://github.com/EDeev)
|
|
||||||
- Email: egor@deev.space
|
|
||||||
- Telegram: [@Egor_Deev](https://t.me/Egor_Deev)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<sub>Разработано в рамках образовательной программы Яндекс Лицея для демонстрации навыков полного цикла веб-разработки</sub>
|
<sub>⭐ Если проект оказался полезным, поставьте звёздочку на GitHub!</sub>
|
||||||
<p><sub>Создано с ❤️ от вашего дорогого - deev.space ©</sub></p>
|
<p><sub>Сделано с ❤️ — <a href="https://deev.space">deev.space</a></sub></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
from flask import Flask, render_template, redirect
|
|
||||||
from loginform import LoginForm
|
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
|
||||||
app.config['SECRET_KEY'] = 'yandexlyceum_secret_key'
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
|
||||||
@app.route('/index')
|
|
||||||
def index(label):
|
|
||||||
param = {'label': 'И на Марсе будут яблони цвести!', 'title': label}
|
|
||||||
return render_template('index.html', **param)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/training/<prof>')
|
|
||||||
def training(prof):
|
|
||||||
param = {'title': "Тренировки в полёте", "spec": prof}
|
|
||||||
return render_template('training.html', **param)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/list_prof/<var>')
|
|
||||||
def list_prof(var):
|
|
||||||
param = {'title': "Список профессий", "var": var}
|
|
||||||
return render_template('list_prof.html', **param)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/answer')
|
|
||||||
@app.route('/auto_answer')
|
|
||||||
def answer():
|
|
||||||
param = {'title': "Анкета", 'surname': "Фёдоров", 'name': "Марк", 'education': "Среднее", 'profession': " Писатель",
|
|
||||||
'sex': "Male", 'motivation': "Распространить хип-хоп в космос!", 'ready': "True"}
|
|
||||||
return render_template('auto_answer.html', **param)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/login', methods=['GET', 'POST'])
|
|
||||||
def login():
|
|
||||||
param = {'title': "Аварийный доступ"}
|
|
||||||
form = LoginForm()
|
|
||||||
if form.validate_on_submit():
|
|
||||||
return redirect('/success')
|
|
||||||
return render_template('login.html', **param, form=form)
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/distribution')
|
|
||||||
def success():
|
|
||||||
param = {'title': "По каютам!", "users": ['Ридли Скотт', 'Энди Уир', 'Марк Уотни', "Венката Капур",
|
|
||||||
'Тедди Сандерс', 'Шон Бин']}
|
|
||||||
return render_template('distribution.html', **param)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
app.run(port=8080, host='127.0.0.1')
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
h4.color_edit {
|
|
||||||
color: "black";
|
|
||||||
}
|
|
||||||
|
|
||||||
p.padmarging {
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
{% extends "base_two.html" %}
|
|
||||||
|
|
||||||
{% block content1 %}
|
|
||||||
<div class="alert alert-light" role="alert">
|
|
||||||
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Фамилия: {{surname}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Имя: {{name}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Образование: {{education}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Профессия: {{profession}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Пол: {{sex}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Мотивация: {{motivation}}</p></h4>
|
|
||||||
<h4 class="color_edit"><p style="padding-left: 60px">Готовы остаться на Марсе? {{ready}}</p></h4>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<!-- Required meta tags -->
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
|
|
||||||
<!-- Bootstrap CSS -->
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
|
|
||||||
rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
|
|
||||||
crossorigin="anonymous">
|
|
||||||
|
|
||||||
<!-- <link rel="stylesheet" type="text/css" href="static/css/style.css" /> -->
|
|
||||||
<title>{{title}}</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header>
|
|
||||||
<nav class="navbar navbar-light bg-light">
|
|
||||||
<div class="container-fluid">
|
|
||||||
<a class="navbar-brand mb-0" href="#"><h1>Миссия Колонизация Марса</h1></a>
|
|
||||||
<div class="navbar-text mb-0 h5">
|
|
||||||
Mars One
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
<!-- Begin page content -->
|
|
||||||
<main role="main" class="container-fluid">
|
|
||||||
{% block content1 %}{% endblock %}
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
{% extends "base_two.html" %}
|
|
||||||
|
|
||||||
{% block content2 %}
|
|
||||||
<h1><img src="../static/img/mars_ico.png">Аварийный доступ</h1><br>
|
|
||||||
<form action="" method="post" novalidate>
|
|
||||||
{{ form.hidden_tag() }}
|
|
||||||
<p>
|
|
||||||
<big>{{ form.id_user.label }}</big>><br>
|
|
||||||
{{ form.id_user(class="form-control") }}<br>
|
|
||||||
{% for error in form.id_user.errors %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<big>{{ form.pas_user.label }}</big><br>
|
|
||||||
{{ form.pas_user(class="form-control", type="password") }}<br>
|
|
||||||
{% for error in form.pas_user.errors %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<big>{{ form.id_cap.label }}</big><br>
|
|
||||||
{{ form.id_cap(class="form-control") }}<br>
|
|
||||||
{% for error in form.id_cap.errors %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<big>{{ form.pas_cap.label }}</big><br>
|
|
||||||
{{ form.pas_cap(class="form-control", type="password") }}<br>
|
|
||||||
{% for error in form.pas_cap.errors %}
|
|
||||||
<div class="alert alert-danger" role="alert">
|
|
||||||
{{ error }}
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
<p>{{ form.submit(type="submit", class="btn btn-primary") }}</p>
|
|
||||||
</form>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
{% extends "base_two.html" %}
|
|
||||||
|
|
||||||
{% block content2 %}
|
|
||||||
{% set sin = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог"] %}
|
|
||||||
{% set inj = ['инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
|
||||||
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
|
||||||
"киберинженер", "штурман", "пилот дронов"] %}
|
|
||||||
{% if spec.lower() in sin %}
|
|
||||||
<p class="text-center h2">Научные симуляторы</p>
|
|
||||||
<p class="text-center"><img src="/static/img/kb1.jpg" class="img-fluid"></p>
|
|
||||||
{% elif spec.lower() in inj %}
|
|
||||||
<p class="text-center h2">Инженерные тренажеры</p>
|
|
||||||
<p class="text-center"><img src="/static/img/kb2.jpg" class="img-fluid"></p>
|
|
||||||
{% else %}
|
|
||||||
<p class="text-center h1">В наших списках ваша профессия отсутствует!</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
from flask_wtf import FlaskForm
|
|
||||||
from wtforms import StringField, PasswordField, BooleanField, SubmitField
|
|
||||||
from wtforms.validators import DataRequired
|
|
||||||
|
|
||||||
|
|
||||||
class LoginForm(FlaskForm):
|
|
||||||
id_user = StringField('Id астронавта', validators=[DataRequired()])
|
|
||||||
pas_user = PasswordField('Пароль астронавта', validators=[DataRequired()])
|
|
||||||
id_cap = StringField('Id капитана', validators=[DataRequired()])
|
|
||||||
pas_cap = PasswordField('Пароль капитана', validators=[DataRequired()])
|
|
||||||
# remember_me = BooleanField('Запомнить меня') <p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
|
|
||||||
submit = SubmitField('Доступ')
|
|
||||||
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 268 KiB |
|
Before Width: | Height: | Size: 267 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
|
@ -1,10 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content1 %}
|
|
||||||
<div class="alert alert-light" role="alert">
|
|
||||||
<h4><font color="#DCDCDC">И на Марсе будут яблони цвести!</font></h4>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
|
||||||
{% block content2 %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
{% extends "base_two.html" %}
|
|
||||||
|
|
||||||
{% block content2 %}
|
|
||||||
<h1 align="center">Размещение по каютам</h1>
|
|
||||||
{% for user in users %}
|
|
||||||
<h3>{{ user }} - Каюта № {{ loop.index }} {% if loop.first %} - первый в очереди {% endif %}</h3>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content1 %}
|
|
||||||
<h4>{{label}}</h4>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
{% extends "base_two.html" %}
|
|
||||||
|
|
||||||
{% block content2 %}
|
|
||||||
{% set all_prof = ['врач', "экзобиолог", "климатолог", "астрогеолог", "гляциолог", "метеоролог",
|
|
||||||
'инженер-исследователь', "пилот", "строитель", "инженер по терраформированию",
|
|
||||||
"специалист по радиационной защите", "инженер жизнеобеспечения", "оператор марсохода",
|
|
||||||
"киберинженер", "штурман", "пилот дронов"] %}
|
|
||||||
{% if var == "ol" %}
|
|
||||||
<p class="h1">Список профессий</p>
|
|
||||||
<div class="container">
|
|
||||||
<ol>
|
|
||||||
{% for p in all_prof %}
|
|
||||||
<li class="h5">{{p}}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
{% elif var == "ul" %}
|
|
||||||
<p class="h1">Список профессий</p>
|
|
||||||
<div class="container">
|
|
||||||
{% for p in all_prof %}
|
|
||||||
<li class="h5">{{p}}</li>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
{% else %}
|
|
||||||
<p class="h1">Индекс указан неправильно!</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
BIN
docs/screenshots/astronaut.png
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
docs/screenshots/promotion.png
Normal file
|
After Width: | Height: | Size: 346 KiB |
|
|
@ -1,23 +1,6 @@
|
||||||
# Core Flask Framework
|
|
||||||
Flask==2.3.3
|
Flask==2.3.3
|
||||||
Jinja2==3.1.2
|
Werkzeug==2.3.8
|
||||||
|
|
||||||
# Flask Extensions
|
|
||||||
Flask-WTF==1.1.1
|
Flask-WTF==1.1.1
|
||||||
WTForms==3.0.1
|
WTForms==3.0.1
|
||||||
|
|
||||||
# HTTP Client Library
|
|
||||||
requests==2.31.0
|
requests==2.31.0
|
||||||
|
|
||||||
# Image Processing
|
|
||||||
Pillow==10.0.1
|
Pillow==10.0.1
|
||||||
|
|
||||||
# Security
|
|
||||||
cryptography==41.0.7
|
|
||||||
|
|
||||||
# Development Dependencies
|
|
||||||
python-dotenv==1.0.0
|
|
||||||
|
|
||||||
# Optional: Testing Framework
|
|
||||||
pytest==7.4.3
|
|
||||||
pytest-flask==1.3.0
|
|
||||||
|
|
|
||||||