|
|
from flask import Flask, render_template_string, request, redirect, url_for |
|
|
import json |
|
|
import os |
|
|
import logging |
|
|
|
|
|
app = Flask(__name__) |
|
|
DATA_FILE = 'products.json' |
|
|
|
|
|
|
|
|
logging.basicConfig(level=logging.DEBUG) |
|
|
|
|
|
|
|
|
def load_data(): |
|
|
if os.path.exists(DATA_FILE): |
|
|
try: |
|
|
with open(DATA_FILE, 'r', encoding='utf-8') as file: |
|
|
return json.load(file) |
|
|
except json.JSONDecodeError: |
|
|
logging.error("Ошибка: Невозможно декодировать JSON файл.") |
|
|
return [] |
|
|
return [] |
|
|
|
|
|
|
|
|
def save_data(data): |
|
|
with open(DATA_FILE, 'w', encoding='utf-8') as file: |
|
|
json.dump(data, file, ensure_ascii=False, indent=4) |
|
|
|
|
|
|
|
|
@app.route('/catalog') |
|
|
def catalog(): |
|
|
products = load_data() |
|
|
catalog_html = ''' |
|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Каталог</title> |
|
|
<style> |
|
|
body { |
|
|
font-family: Arial, sans-serif; |
|
|
margin: 20px; |
|
|
background-color: #f9f9f9; |
|
|
} |
|
|
h1 { |
|
|
color: #333; |
|
|
} |
|
|
.product { |
|
|
background-color: #fff; |
|
|
border: 1px solid #ddd; |
|
|
padding: 15px; |
|
|
margin-bottom: 10px; |
|
|
border-radius: 5px; |
|
|
} |
|
|
.product h2 { |
|
|
margin-top: 0; |
|
|
color: #555; |
|
|
} |
|
|
.product p { |
|
|
color: #777; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<h1>Каталог товаров</h1> |
|
|
{% for product in products %} |
|
|
<div class="product"> |
|
|
<h2>{{ product['name'] }}</h2> |
|
|
<p><strong>Цена:</strong> {{ product['price'] }} руб.</p> |
|
|
<p><strong>Описание:</strong> {{ product['description'] }}</p> |
|
|
</div> |
|
|
{% endfor %} |
|
|
</body> |
|
|
</html> |
|
|
''' |
|
|
return render_template_string(catalog_html, products=products) |
|
|
|
|
|
|
|
|
@app.route('/admin', methods=['GET', 'POST']) |
|
|
def admin(): |
|
|
if request.method == 'POST': |
|
|
name = request.form.get('name') |
|
|
price = request.form.get('price') |
|
|
description = request.form.get('description') |
|
|
|
|
|
logging.debug(f"Полученные данные из формы: name={name}, price={price}, description={description}") |
|
|
|
|
|
if name and price and description: |
|
|
try: |
|
|
price = float(price) |
|
|
except ValueError: |
|
|
logging.error("Ошибка: Цена должна быть числом.") |
|
|
return "Ошибка: Цена должна быть числом.", 400 |
|
|
|
|
|
products = load_data() |
|
|
products.append({ |
|
|
'name': name, |
|
|
'price': price, |
|
|
'description': description |
|
|
}) |
|
|
save_data(products) |
|
|
return redirect(url_for('admin')) |
|
|
|
|
|
products = load_data() |
|
|
admin_html = ''' |
|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Админ-панель</title> |
|
|
<style> |
|
|
body { |
|
|
font-family: Arial, sans-serif; |
|
|
margin: 20px; |
|
|
background-color: #f9f9f9; |
|
|
} |
|
|
h1 { |
|
|
color: #333; |
|
|
} |
|
|
form { |
|
|
background-color: #fff; |
|
|
padding: 20px; |
|
|
border: 1px solid #ddd; |
|
|
border-radius: 5px; |
|
|
max-width: 400px; |
|
|
} |
|
|
label { |
|
|
display: block; |
|
|
margin-top: 10px; |
|
|
color: #555; |
|
|
} |
|
|
input, textarea { |
|
|
width: 100%; |
|
|
padding: 8px; |
|
|
margin-top: 5px; |
|
|
border: 1px solid #ddd; |
|
|
border-radius: 4px; |
|
|
} |
|
|
button { |
|
|
margin-top: 15px; |
|
|
padding: 10px 15px; |
|
|
background-color: #28a745; |
|
|
color: white; |
|
|
border: none; |
|
|
border-radius: 4px; |
|
|
cursor: pointer; |
|
|
} |
|
|
button:hover { |
|
|
background-color: #218838; |
|
|
} |
|
|
.product-list { |
|
|
margin-top: 20px; |
|
|
} |
|
|
.product-item { |
|
|
background-color: #fff; |
|
|
border: 1px solid #ddd; |
|
|
padding: 10px; |
|
|
margin-bottom: 10px; |
|
|
border-radius: 5px; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body> |
|
|
<h1>Добавление товара</h1> |
|
|
<form method="POST"> |
|
|
<label for="name">Название товара:</label> |
|
|
<input type="text" id="name" name="name" required> |
|
|
|
|
|
<label for="price">Цена:</label> |
|
|
<input type="number" id="price" name="price" step="0.01" required> |
|
|
|
|
|
<label for="description">Описание:</label> |
|
|
<textarea id="description" name="description" rows="4" required></textarea> |
|
|
|
|
|
<button type="submit">Добавить товар</button> |
|
|
</form> |
|
|
|
|
|
<div class="product-list"> |
|
|
<h2>Список товаров</h2> |
|
|
{% for product in products %} |
|
|
<div class="product-item"> |
|
|
<strong>{{ product['name'] }}</strong> - {{ product['price'] }} руб. |
|
|
<p>{{ product['description'] }}</p> |
|
|
</div> |
|
|
{% endfor %} |
|
|
</div> |
|
|
</body> |
|
|
</html> |
|
|
''' |
|
|
return render_template_string(admin_html, products=products) |
|
|
|
|
|
if __name__ == '__main__': |
|
|
app.run(host='0.0.0.0', port=7860) |