flpolprojects commited on
Commit
df913b7
·
verified ·
1 Parent(s): 38ac451

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -193
app.py CHANGED
@@ -150,10 +150,11 @@ def catalog():
150
  /* Медиа-запрос для мобильных устройств */
151
  @media (max-width: 768px) {
152
  .product-grid {
153
- grid-template-columns: 1fr; /* Одна колонка на мобильных */
 
154
  }
155
  .product {
156
- padding: 10px;
157
  }
158
  }
159
  </style>
@@ -267,195 +268,195 @@ def admin():
267
  products[index]['photo'] = photo_filename # Обновляем имя файла
268
  except Exception as e:
269
  logging.error(f"Ошибка при загрузке фото: {e}")
270
- return f"Ошибка при загрузке фото: {e}", 500
271
- finally:
272
- os.remove(temp_path)
273
 
274
- # Обновление остальных полей
275
- products[index]['name'] = name
276
- try:
277
- price = float(price.replace(',', '.'))
278
- except ValueError:
279
- logging.error("Ошибка: Цена должна быть числом.")
280
- return "Ошибка: Цена должна быть числом.", 400
281
- products[index]['price'] = price
282
- products[index]['description'] = description
283
-
284
- save_data(products)
285
- return redirect(url_for('admin'))
286
-
287
- elif action == 'delete':
288
- index = int(request.form.get('index'))
289
- del products[index]
290
- save_data(products)
291
- return redirect(url_for('admin'))
292
-
293
- admin_html = '''
294
- <!DOCTYPE html>
295
- <html lang="ru">
296
- <head>
297
- <meta charset="UTF-8">
298
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
299
- <title>Админ-панель</title>
300
- <style>
301
- body {
302
- font-family: Arial, sans-serif;
303
- margin: 20px;
304
- background-color: #f9f9f9;
305
- }
306
- h1 {
307
- color: #333;
308
- }
309
- form {
310
- background-color: #fff;
311
- padding: 20px;
312
- border: 1px solid #ddd;
313
- border-radius: 5px;
314
- max-width: 400px;
315
- margin-bottom: 20px;
316
- }
317
- label {
318
- display: block;
319
- margin-top: 10px;
320
- color: #555;
321
- }
322
- input, textarea {
323
- width: 100%;
324
- padding: 8px;
325
- margin-top: 5px;
326
- border: 1px solid #ddd;
327
- border-radius: 4px;
328
- }
329
- button {
330
- margin-top: 15px;
331
- padding: 10px 15px;
332
- background-color: #28a745;
333
- color: white;
334
- border: none;
335
- border-radius: 4px;
336
- cursor: pointer;
337
- }
338
- button:hover {
339
- background-color: #218838;
340
- }
341
- .product-list {
342
- margin-top: 20px;
343
- }
344
- .product-item {
345
- background-color: #fff;
346
- border: 1px solid #ddd;
347
- padding: 15px;
348
- margin-bottom: 10px;
349
- border-radius: 5px;
350
- }
351
- .edit-form {
352
- margin-top: 10px;
353
- padding: 10px;
354
- border: 1px solid #ddd;
355
- border-radius: 5px;
356
- background-color: #f9f9f9;
357
- }
358
- </style>
359
- </head>
360
- <body>
361
- <h1>Добавление товара</h1>
362
- <form method="POST" enctype="multipart/form-data">
363
- <input type="hidden" name="action" value="add">
364
- <label for="name">Название товара:</label>
365
- <input type="text" id="name" name="name" required>
366
-
367
- <label for="price">Цена:</label>
368
- <input type="number" id="price" name="price" step="0.01" required>
369
-
370
- <label for="description">Описание:</label>
371
- <textarea id="description" name="description" rows="4" required></textarea>
372
-
373
- <label for="photo">Фотография товара (необязательно):</label>
374
- <input type="file" id="photo" name="photo" accept="image/*">
375
-
376
- <button type="submit">Добавить товар</button>
377
- </form>
378
-
379
- <h2>Управление базой данных</h2>
380
-
381
- <!-- Кнопки для резервной копии и скачивания -->
382
- <form method="POST" action="{{ url_for('backup') }}">
383
- <button type="submit">Создать резервную копию</button>
384
- </form>
385
-
386
- <form method="GET" action="{{ url_for('download') }}">
387
- <button type="submit">Скачать базу данных</button>
388
- </form>
389
-
390
- <h2>Список товаров</h2>
391
- <div class="product-list">
392
- {% for product in products %}
393
- <div class="product-item">
394
- <h3>{{ product['name'] }}</h3>
395
- <p><strong>Цена:</strong> {{ product['price'] }} руб.</p>
396
- <p><strong>Описание:</strong> {{ product['description'] }}</p>
397
- {% if product.get('photo') %}
398
- <img src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/photos/{{ product['photo'] }}" alt="{{ product['name'] }}" style="max-width: 100px;">
399
- {% endif %}
400
-
401
- <details>
402
- <summary>Редактировать</summary>
403
- <form method="POST" enctype="multipart/form-data" class="edit-form">
404
- <input type="hidden" name="action" value="edit">
405
- <input type="hidden" name="index" value="{{ loop.index0 }}">
406
- <label for="name">Название товара:</label>
407
- <input type="text" id="name" name="name" value="{{ product['name'] }}" required>
408
-
409
- <label for="price">Цена:</label>
410
- <input type="number" id="price" name="price" step="0.01" value="{{ product['price'] }}" required>
411
-
412
- <label for="description">Описание:</label>
413
- <textarea id="description" name="description" rows="4" required>{{ product['description'] }}</textarea>
414
-
415
- <label for="photo">Фотография товара (необязательно):</label>
416
- <input type="file" id="photo" name="photo" accept="image/*">
417
-
418
- <button type="submit">Сохранить изменения</button>
419
- </form>
420
- </details>
421
-
422
- <form method="POST">
423
- <input type="hidden" name="action" value="delete">
424
- <input type="hidden" name="index" value="{{ loop.index0 }}">
425
- <button type="submit">Удалить</button>
426
- </form>
427
- </div>
428
- {% endfor %}
429
- </div>
430
-
431
- </body>
432
- </html>
433
- '''
434
- return render_template_string(admin_html, products=products, repo_id=REPO_ID)
435
-
436
- @app.route('/backup', methods=['POST'])
437
- def backup():
438
- """Маршрут для создания резервной копии."""
439
- upload_db_to_hf()
440
- return "Резервная копия успешно создана.", 200
441
-
442
- @app.route('/download', methods=['GET'])
443
- def download():
444
- """Маршрут для скачивания базы данных."""
445
- download_db_from_hf()
446
- return "База данных успешно скачана.", 200
447
-
448
- if __name__ == '__main__':
449
- # Запуск фонового потока для периодического резервного копирования
450
- backup_thread = threading.Thread(target=periodic_backup, daemon=True)
451
- backup_thread.start()
452
-
453
- # Попытка загрузить базу данных из репозитория перед запуском приложения
454
- try:
455
- load_data()
456
- except Exception as e:
457
- logging.error(f"Не удалось загрузить базу данных при запуске: {e}")
458
- # Здесь можно добавить логику для создания пустой базы данных, если это необходимо
459
- # Например: save_data([])
460
-
461
- app.run(debug=True, host='0.0.0.0', port=7860)
 
150
  /* Медиа-запрос для мобильных устройств */
151
  @media (max-width: 768px) {
152
  .product-grid {
153
+ grid-template-columns: repeat(3, 1fr); /* Три колонки на мобильных устройствах */
154
+ gap: 20px; /* Промежуток между колонками */
155
  }
156
  .product {
157
+ padding: 10px; /* Уменьшение отступов на мобильных */
158
  }
159
  }
160
  </style>
 
268
  products[index]['photo'] = photo_filename # Обновляем имя файла
269
  except Exception as e:
270
  logging.error(f"Ошибка при загрузке фото: {e}")
271
+ return f"Ошибка при загрузке фото: {e}", 500
272
+ finally:
273
+ os.remove(temp_path)
274
 
275
+ # Обновление остальных полей
276
+ products[index]['name'] = name
277
+ try:
278
+ price = float(price.replace(',', '.'))
279
+ except ValueError:
280
+ logging.error("Ошибка: Цена должна быть числом.")
281
+ return "Ошибка: Цена должна быть числом.", 400
282
+ products[index]['price'] = price
283
+ products[index]['description'] = description
284
+
285
+ save_data(products)
286
+ return redirect(url_for('admin'))
287
+
288
+ elif action == 'delete':
289
+ index = int(request.form.get('index'))
290
+ del products[index]
291
+ save_data(products)
292
+ return redirect(url_for('admin'))
293
+
294
+ admin_html = '''
295
+ <!DOCTYPE html>
296
+ <html lang="ru">
297
+ <head>
298
+ <meta charset="UTF-8">
299
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
300
+ <title>Админ-панель</title>
301
+ <style>
302
+ body {
303
+ font-family: Arial, sans-serif;
304
+ margin: 20px;
305
+ background-color: #f9f9f9;
306
+ }
307
+ h1 {
308
+ color: #333;
309
+ }
310
+ form {
311
+ background-color: #fff;
312
+ padding: 20px;
313
+ border: 1px solid #ddd;
314
+ border-radius: 5px;
315
+ max-width: 400px;
316
+ margin-bottom: 20px;
317
+ }
318
+ label {
319
+ display: block;
320
+ margin-top: 10px;
321
+ color:#555;
322
+ }
323
+ input, textarea {
324
+ width :100%;
325
+ padding :8 px ;
326
+ margin-top :5 px ;
327
+ border :1 px solid#ddd ;
328
+ border-radius :4 px ;
329
+ }
330
+ button{
331
+ margin-top :15 px ;
332
+ padding :10 px15 px ;
333
+ background-color :#28 a745 ;
334
+ color:white ;
335
+ border:none ;
336
+ border-radius :4 px ;
337
+ cursor:pointer ;
338
+ }
339
+ button:hover{
340
+ background-color :#218838 ;
341
+ }
342
+ .product-list{
343
+ margin-top :20 px ;
344
+ }
345
+ .product-item{
346
+ background-color :#fff ;
347
+ border :1 px solid#ddd ;
348
+ padding :15 px ;
349
+ margin-bottom :10 px ;
350
+ border-radius :5 px ;
351
+ }
352
+ .edit-form{
353
+ margin-top :10 px ;
354
+ padding :10 px ;
355
+ border :1 px solid#ddd ;
356
+ border-radius :5 px ;
357
+ background-color :#f9f9f9 ;
358
+ }
359
+ </style>
360
+ </head>
361
+ <body>
362
+ <h1>Добавление товара</h1>
363
+ <form method="POST" enctype="multipart/form-data">
364
+ <input type="hidden" name="action" value="add">
365
+ <label for="name">Название товара:</label>
366
+ <input type="text" id="name" name="name" required>
367
+
368
+ <label for="price">Цена:</label>
369
+ <input type="number" id="price" name="price" step="0.01" required>
370
+
371
+ <label for="description">Описание:</label>
372
+ <textarea id="description" name="description" rows="4" required></textarea>
373
+
374
+ <label for="photo">Фотография товара (необязательно):</label>
375
+ <input type="file" id="photo" name="photo" accept="image/*">
376
+
377
+ <button type="submit">Добавить товар</button>
378
+ </form>
379
+
380
+ <h2>Управление базой данных</h2>
381
+
382
+ <!-- Кнопки для резервной копии и скачивания -->
383
+ <form method="POST" action="{{ url_for('backup') }}">
384
+ <button type="submit">Создать резервную копию</button>
385
+ </form>
386
+
387
+ <form method="GET" action="{{ url_for('download') }}">
388
+ <button type="submit">Скачать базу данных</button>
389
+ </form>
390
+
391
+ <h2>Список товаров</h2>
392
+ <div class="product-list">
393
+ {% for product in products %}
394
+ <div class="product-item">
395
+ <h3>{{ product['name'] }}</h3>
396
+ <p><strong>Цена:</strong>{{ product['price'] }} руб.</p>
397
+ <p><strong>Описание:</strong>{{ product['description'] }}</p>
398
+ {% if product.get('photo') %}
399
+ <img src ="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/photos/{{ product['photo'] }}" alt="{{ product['name'] }}" style ="max-width :100 px;">
400
+ {% endif %}
401
+
402
+ <details >
403
+ <summary >Редактировать</summary >
404
+ <form method ="POST " enctype ="multipart/form-data " class ="edit-form ">
405
+ <input type ="hidden " name ="action " value ="edit ">
406
+ <input type ="hidden " name ="index " value="{{ loop.index0 }}">
407
+ <label for ="name ">Название товара:</label >
408
+ <input type ="text " id ="name " name ="name " value="{{ product['name'] }}" required >
409
+
410
+ <label for ="price ">Цена:</label >
411
+ <input type ="number " id ="price " name ="price " step ="0.01 " value="{{ product['price'] }}" required >
412
+
413
+ <label for ="description ">Описание:</label >
414
+ <textarea id ="description " name ="description " rows ="4 " required >{{ product['description'] }}</textarea >
415
+
416
+ <label for ="photo ">Фотография товара (необязательно):</label >
417
+ <input type ="file " id ="photo " name ="photo " accept ="image/* ">
418
+
419
+ <button type ="submit ">Сохранить изменения</button >
420
+ </form >
421
+ </details >
422
+
423
+ <form method ="POST ">
424
+ <input type ="hidden " name ="action " value ="delete ">
425
+ <input type ="hidden " name ="index " value="{{ loop.index0 }}">
426
+ <button type ="submit ">Удалить</button >
427
+ </form >
428
+ </div >
429
+ {% endfor %}
430
+ </div >
431
+
432
+ </body >
433
+ </html >
434
+ '''
435
+ return render_template_string(admin_html , products=products , repo_id=REPO_ID)
436
+
437
+ @app.route('/backup' , methods=['POST'])
438
+ def backup():
439
+ """Маршрут для создания резервной копии."""
440
+ upload_db_to_hf()
441
+ return "Резервная копия успешно создана." ,200
442
+
443
+ @app.route('/download' , methods=['GET'])
444
+ def download():
445
+ """Маршрут для скачивания базы данных."""
446
+ download_db_from_hf()
447
+ return "База данных успешно скачана." ,200
448
+
449
+ if __name__ == '__main__':
450
+ # Запуск фонового потока для периодического резервного копирования
451
+ backup_thread = threading.Thread(target=periodic_backup , daemon=True)
452
+ backup_thread.start()
453
+
454
+ # Попытка загрузить базу данных из репозитория перед запуском приложения
455
+ try :
456
+ load_data()
457
+ except Exception as e :
458
+ logging.error(f"Не удалось загрузить базу данных при запуске:{e}")
459
+ # Здесь можно добавить логику для создания пустой базы данных , если это необходимо
460
+ # Например:savedata([])
461
+
462
+ app.run(debug=True , host='0.0.0.0' , port=7860)