Update app.py
Browse files
app.py
CHANGED
|
@@ -50,10 +50,10 @@ def initialize_data_structure(data):
|
|
| 50 |
if not isinstance(product['photos'], list):
|
| 51 |
product['photos'] = []
|
| 52 |
|
| 53 |
-
if 'media' in product:
|
| 54 |
del product['media']
|
| 55 |
|
| 56 |
-
product.pop('in_stock', None)
|
| 57 |
product.pop('is_top', None)
|
| 58 |
|
| 59 |
return data
|
|
@@ -151,7 +151,7 @@ def periodic_backup():
|
|
| 151 |
upload_db_to_hf()
|
| 152 |
except Exception as e:
|
| 153 |
logging.error(f"Ошибка при выполнении периодического резервного копирования: {e}")
|
| 154 |
-
time.sleep(3600)
|
| 155 |
|
| 156 |
def allowed_file(filename):
|
| 157 |
return '.' in filename and \
|
|
@@ -161,7 +161,7 @@ def allowed_file(filename):
|
|
| 161 |
def catalog():
|
| 162 |
data = load_data()
|
| 163 |
products = data['products']
|
| 164 |
-
categories = data['categories']
|
| 165 |
|
| 166 |
catalog_html = '''
|
| 167 |
<!DOCTYPE html>
|
|
@@ -972,7 +972,7 @@ def catalog():
|
|
| 972 |
|
| 973 |
let cart = JSON.parse(localStorage.getItem('cart') || '[]');
|
| 974 |
const product = products[selectedProductIndex];
|
| 975 |
-
const cartItemId = `${product.id}-${color}-${model}`;
|
| 976 |
const existingItem = cart.find(item => item.id === cartItemId);
|
| 977 |
|
| 978 |
if (existingItem) {
|
|
@@ -980,7 +980,7 @@ def catalog():
|
|
| 980 |
} else {
|
| 981 |
cart.push({
|
| 982 |
id: cartItemId,
|
| 983 |
-
product_id: product.id,
|
| 984 |
name: product.name,
|
| 985 |
price: product.price,
|
| 986 |
photo: product.photos && product.photos.length > 0 ? product.photos[0] : '',
|
|
@@ -1010,15 +1010,15 @@ def catalog():
|
|
| 1010 |
cartContent.innerHTML = cart.length === 0 ? '<p style="text-align: center; color: var(--secondary-text-color-light);">Корзина пуста</p>' : cart.map(item => {
|
| 1011 |
const itemTotal = item.price * item.quantity;
|
| 1012 |
total += itemTotal;
|
| 1013 |
-
const photoSrc = item.photo ? `https://huggingface.co/datasets/{{ repo_id }}/resolve/main/photos/${item.photo}` : 'https://via.placeholder.com/60x60?text=No+Image';
|
| 1014 |
return `
|
| 1015 |
<div class="cart-item">
|
| 1016 |
<img src="${photoSrc}" alt="${item.name}">
|
| 1017 |
<div class="cart-item-details">
|
| 1018 |
<strong>${item.name}</strong>
|
| 1019 |
-
<p>${item.price} с × ${item.quantity} (Цвет: ${item.color}, Модель: ${item.model})</p>
|
| 1020 |
</div>
|
| 1021 |
-
<span class="cart-item-total">${itemTotal} с</span>
|
| 1022 |
</div>
|
| 1023 |
`;
|
| 1024 |
}).join('');
|
|
@@ -1038,7 +1038,7 @@ def catalog():
|
|
| 1038 |
cart.forEach((item, index) => {
|
| 1039 |
const itemTotal = item.price * item.quantity;
|
| 1040 |
total += itemTotal;
|
| 1041 |
-
orderText += `${index + 1}. ${item.name}%0AКоличество: ${item.quantity}%0AЦена: ${item.price} с%0AЦвет: ${item.color}%0AМодель: ${item.model}%0A--%0A`;
|
| 1042 |
});
|
| 1043 |
orderText += `*Итого к оплате: ${total.toFixed(2)} с*%0A%0AЖду подтверждения заказа.`;
|
| 1044 |
window.open(`https://api.whatsapp.com/send?phone=996705665777&text=${orderText}`, '_blank');
|
|
@@ -1131,7 +1131,7 @@ def product_modal_content(index):
|
|
| 1131 |
def admin():
|
| 1132 |
data = load_data()
|
| 1133 |
products = data['products']
|
| 1134 |
-
categories = data['categories']
|
| 1135 |
|
| 1136 |
if request.method == 'POST':
|
| 1137 |
action = request.form.get('action')
|
|
@@ -1184,15 +1184,17 @@ def admin():
|
|
| 1184 |
flash('Ошибка: Неверный формат цены.', 'error')
|
| 1185 |
return redirect(url_for('admin'))
|
| 1186 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1187 |
if photos_files and any(f.filename for f in photos_files):
|
| 1188 |
-
uploads_dir = 'uploads'
|
| 1189 |
-
os.makedirs(uploads_dir, exist_ok=True)
|
| 1190 |
api = HfApi()
|
| 1191 |
for i, photo in enumerate(photos_files[:10]):
|
| 1192 |
if photo and photo.filename and allowed_file(photo.filename):
|
| 1193 |
base, extension = os.path.splitext(photo.filename)
|
| 1194 |
unique_filename = secure_filename(f"{name.replace(' ','_')}_{int(time.time())}_{i}{extension}")
|
| 1195 |
-
temp_path = os.path.join(
|
| 1196 |
try:
|
| 1197 |
photo.save(temp_path)
|
| 1198 |
api.upload_file(
|
|
@@ -1262,16 +1264,17 @@ def admin():
|
|
| 1262 |
products[index]['colors'] = colors
|
| 1263 |
products[index]['models'] = models
|
| 1264 |
|
|
|
|
|
|
|
|
|
|
| 1265 |
if photos_files and any(f.filename for f in photos_files):
|
| 1266 |
new_photos_list = []
|
| 1267 |
-
uploads_dir = 'uploads'
|
| 1268 |
-
os.makedirs(uploads_dir, exist_ok=True)
|
| 1269 |
api = HfApi()
|
| 1270 |
for i, photo in enumerate(photos_files[:10]):
|
| 1271 |
if photo and photo.filename and allowed_file(photo.filename):
|
| 1272 |
base, extension = os.path.splitext(photo.filename)
|
| 1273 |
unique_filename = secure_filename(f"{name.replace(' ','_')}_{int(time.time())}_{i}{extension}")
|
| 1274 |
-
temp_path = os.path.join(
|
| 1275 |
try:
|
| 1276 |
photo.save(temp_path)
|
| 1277 |
api.upload_file(
|
|
@@ -1818,8 +1821,10 @@ def download():
|
|
| 1818 |
return redirect(url_for('admin'))
|
| 1819 |
|
| 1820 |
if __name__ == '__main__':
|
| 1821 |
-
|
| 1822 |
-
|
|
|
|
|
|
|
| 1823 |
|
| 1824 |
logging.info("Начальная проверка и обновление структуры данных...")
|
| 1825 |
try:
|
|
|
|
| 50 |
if not isinstance(product['photos'], list):
|
| 51 |
product['photos'] = []
|
| 52 |
|
| 53 |
+
if 'media' in product: # Ensure 'media' field is completely removed if it exists
|
| 54 |
del product['media']
|
| 55 |
|
| 56 |
+
product.pop('in_stock', None) # Remove obsolete fields
|
| 57 |
product.pop('is_top', None)
|
| 58 |
|
| 59 |
return data
|
|
|
|
| 151 |
upload_db_to_hf()
|
| 152 |
except Exception as e:
|
| 153 |
logging.error(f"Ошибка при выполнении периодического резервного копирования: {e}")
|
| 154 |
+
time.sleep(3600)
|
| 155 |
|
| 156 |
def allowed_file(filename):
|
| 157 |
return '.' in filename and \
|
|
|
|
| 161 |
def catalog():
|
| 162 |
data = load_data()
|
| 163 |
products = data['products']
|
| 164 |
+
categories = sorted(data['categories'])
|
| 165 |
|
| 166 |
catalog_html = '''
|
| 167 |
<!DOCTYPE html>
|
|
|
|
| 972 |
|
| 973 |
let cart = JSON.parse(localStorage.getItem('cart') || '[]');
|
| 974 |
const product = products[selectedProductIndex];
|
| 975 |
+
const cartItemId = `${product.id}-${color}-${model}`;
|
| 976 |
const existingItem = cart.find(item => item.id === cartItemId);
|
| 977 |
|
| 978 |
if (existingItem) {
|
|
|
|
| 980 |
} else {
|
| 981 |
cart.push({
|
| 982 |
id: cartItemId,
|
| 983 |
+
product_id: product.id,
|
| 984 |
name: product.name,
|
| 985 |
price: product.price,
|
| 986 |
photo: product.photos && product.photos.length > 0 ? product.photos[0] : '',
|
|
|
|
| 1010 |
cartContent.innerHTML = cart.length === 0 ? '<p style="text-align: center; color: var(--secondary-text-color-light);">Корзина пуста</p>' : cart.map(item => {
|
| 1011 |
const itemTotal = item.price * item.quantity;
|
| 1012 |
total += itemTotal;
|
| 1013 |
+
const photoSrc = item.photo ? `https://huggingface.co/datasets/{{ repo_id }}/resolve/main/photos/${item.photo}?r={{ random.randint(1,1000) }}` : 'https://via.placeholder.com/60x60?text=No+Image';
|
| 1014 |
return `
|
| 1015 |
<div class="cart-item">
|
| 1016 |
<img src="${photoSrc}" alt="${item.name}">
|
| 1017 |
<div class="cart-item-details">
|
| 1018 |
<strong>${item.name}</strong>
|
| 1019 |
+
<p>${item.price.toFixed(2)} с × ${item.quantity} (Цвет: ${item.color}, Модель: ${item.model})</p>
|
| 1020 |
</div>
|
| 1021 |
+
<span class="cart-item-total">${itemTotal.toFixed(2)} с</span>
|
| 1022 |
</div>
|
| 1023 |
`;
|
| 1024 |
}).join('');
|
|
|
|
| 1038 |
cart.forEach((item, index) => {
|
| 1039 |
const itemTotal = item.price * item.quantity;
|
| 1040 |
total += itemTotal;
|
| 1041 |
+
orderText += `${index + 1}. ${item.name}%0AКоличество: ${item.quantity}%0AЦена: ${item.price.toFixed(2)} с%0AЦвет: ${item.color}%0AМодель: ${item.model}%0A--%0A`;
|
| 1042 |
});
|
| 1043 |
orderText += `*Итого к оплате: ${total.toFixed(2)} с*%0A%0AЖду подтверждения заказа.`;
|
| 1044 |
window.open(`https://api.whatsapp.com/send?phone=996705665777&text=${orderText}`, '_blank');
|
|
|
|
| 1131 |
def admin():
|
| 1132 |
data = load_data()
|
| 1133 |
products = data['products']
|
| 1134 |
+
categories = sorted(data['categories'])
|
| 1135 |
|
| 1136 |
if request.method == 'POST':
|
| 1137 |
action = request.form.get('action')
|
|
|
|
| 1184 |
flash('Ошибка: Неверный формат цены.', 'error')
|
| 1185 |
return redirect(url_for('admin'))
|
| 1186 |
|
| 1187 |
+
# Change UPLOAD_FOLDER to /tmp for temporary file storage
|
| 1188 |
+
UPLOAD_TEMP_DIR = '/tmp'
|
| 1189 |
+
os.makedirs(UPLOAD_TEMP_DIR, exist_ok=True)
|
| 1190 |
+
|
| 1191 |
if photos_files and any(f.filename for f in photos_files):
|
|
|
|
|
|
|
| 1192 |
api = HfApi()
|
| 1193 |
for i, photo in enumerate(photos_files[:10]):
|
| 1194 |
if photo and photo.filename and allowed_file(photo.filename):
|
| 1195 |
base, extension = os.path.splitext(photo.filename)
|
| 1196 |
unique_filename = secure_filename(f"{name.replace(' ','_')}_{int(time.time())}_{i}{extension}")
|
| 1197 |
+
temp_path = os.path.join(UPLOAD_TEMP_DIR, unique_filename)
|
| 1198 |
try:
|
| 1199 |
photo.save(temp_path)
|
| 1200 |
api.upload_file(
|
|
|
|
| 1264 |
products[index]['colors'] = colors
|
| 1265 |
products[index]['models'] = models
|
| 1266 |
|
| 1267 |
+
UPLOAD_TEMP_DIR = '/tmp'
|
| 1268 |
+
os.makedirs(UPLOAD_TEMP_DIR, exist_ok=True)
|
| 1269 |
+
|
| 1270 |
if photos_files and any(f.filename for f in photos_files):
|
| 1271 |
new_photos_list = []
|
|
|
|
|
|
|
| 1272 |
api = HfApi()
|
| 1273 |
for i, photo in enumerate(photos_files[:10]):
|
| 1274 |
if photo and photo.filename and allowed_file(photo.filename):
|
| 1275 |
base, extension = os.path.splitext(photo.filename)
|
| 1276 |
unique_filename = secure_filename(f"{name.replace(' ','_')}_{int(time.time())}_{i}{extension}")
|
| 1277 |
+
temp_path = os.path.join(UPLOAD_TEMP_DIR, unique_filename)
|
| 1278 |
try:
|
| 1279 |
photo.save(temp_path)
|
| 1280 |
api.upload_file(
|
|
|
|
| 1821 |
return redirect(url_for('admin'))
|
| 1822 |
|
| 1823 |
if __name__ == '__main__':
|
| 1824 |
+
# UPLOAD_FOLDER is no longer used, but let's keep this if other parts need a generic 'uploads' folder
|
| 1825 |
+
# For temporary file storage, we now use '/tmp' directly in the admin functions.
|
| 1826 |
+
# uploads_dir = 'uploads'
|
| 1827 |
+
# os.makedirs(uploads_dir, exist_ok=True)
|
| 1828 |
|
| 1829 |
logging.info("Начальная проверка и обновление структуры данных...")
|
| 1830 |
try:
|