-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
335 lines (282 loc) · 14.1 KB
/
app.py
File metadata and controls
335 lines (282 loc) · 14.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
from flask import render_template, redirect, request, flash, url_for, session
from flask import Flask
from flask_ngrok import run_with_ngrok
import data
from data import db_session, products, users, cart
from forms.registration import RegistrationForm
from flask_login import LoginManager, login_user, login_required, logout_user, current_user
from forms.login import LoginForm
from sqlalchemy.orm import Query
from flask_wtf.csrf import CSRFProtect
from flask_uploads import UploadSet, IMAGES
from werkzeug.utils import secure_filename
from flask_dropzone import Dropzone
import os
# Создаем экземпляр CSRFProtect
csrf = CSRFProtect()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'yandexlyceum_secret_key'
app.config['FLASK_DEBUG'] = 1
# дебаг нужен для отлавливания и исправления ошибок в реальном времени
login_manager = LoginManager()
login_manager.init_app(app)
csrf.init_app(app) # csrf токен для предотвращения поддельных запросов
# создаем экземпляры расширений
photos = UploadSet('photos', IMAGES)
dropzone = Dropzone(app)
# добавляем конфигурацию для загрузки файлов
app.config['UPLOAD_FOLDER'] = 'static/uploads/photos'
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image'
app.config['DROPZONE_MAX_FILES'] = 1
app.config['DROPZONE_UPLOAD_MULTIPLE'] = False
def format_goods_count(count: int):
if count % 10 == 1 and count % 100 != 11:
return f"{count} предмет"
elif count % 10 in [2, 3, 4] and count % 100 not in [12, 13, 14]:
return f"{count} предмета"
else:
return f"{count} предметов"
@app.route('/registration', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
User = data.users.User
db_sess = db_session.create_session()
if form.validate_on_submit(): # если форма регистрации на подтверждение, то...
if form.password.data != form.confirm_password.data:
flash(message='Пароли не совпадают',
category='danger') # Выдача предупреждения на следующую страницу, в html файле есть обработчик
# для flash предупреждений (далее также)
return redirect('/registration') # Перенаправление на страницу регистрации
if db_sess.query(User).filter(User.username == form.username.data).first():
flash(message='Пользователь с таким именем пользователя уже существует', category='warning ')
return redirect('/registration') # Перенаправление на страницу регистрации
user = User()
user.username = form.username.data
user.password = form.password.data
user.set_password(form.password.data)
db_sess.add(user)
db_sess.commit()
flash(message='Регистрация прошла успешно', category='success') # Выдача сообщения об успешной регистрации
return redirect('/login')
return render_template('registration.html', title='Регистрация', form=form)
@login_manager.user_loader # для сессии
def load_user(user_id):
User = data.users.User
db_sess = db_session.create_session()
return db_sess.query(User).get(user_id)
@app.route('/logout') # выход
@login_required
def logout():
logout_user()
return redirect("/")
@app.route('/login', methods=['GET', 'POST'])
def login():
User = data.users.User
form = LoginForm()
if form.validate_on_submit():
db_sess = db_session.create_session()
user = db_sess.query(User).filter(User.username == form.username.data).first()
if user and user.check_password(form.password.data): # проверяет хеш пароля через функцию внутри класса юзер
login_user(user, remember=form.remember_me.data)
return redirect("/")
flash(message='Неправильный логин или пароль', category='danger')
return redirect('/login')
return render_template('login.html', title='Авторизация', form=form)
@app.route('/') # главная страница
def main_page():
Product = data.products.Product
db_sess = db_session.create_session()
products = db_sess.query(Product).limit(3).all() # выбор 3 продуктов для отображения на главной странице
d = {'src1': url_for('static', filename='img/mars2.jpg'),
'src2': url_for('static', filename='img/mars1.jpg'),
'src3': url_for('static', filename='img/mars3.jpg')}
# Проверка на наличие товаров
if products:
return render_template('main_page.html', products=products, enumerate=enumerate, **d)
else:
return render_template('main_page.html', products=[], enumerate=enumerate, **d)
# добавляем обработчик для загрузки файлов
@app.route('/upload', methods=['POST'])
def upload_photo():
file = request.files.get('file')
if file:
filename = photos.save(file)
return filename
else:
return 'error'
@app.route('/products', methods=['GET', 'POST']) # страница товаров
def products():
db_sess = db_session.create_session()
Product = data.products.Product
if request.method == 'POST':
if 'delete' in request.form: # если нажата кнопка удалить
# Получаем ID продукта для удаления
product_id = int(request.form['delete'])
# Находим объект Product по ID
product_to_delete = db_sess.query(Product).get(product_id)
if product_to_delete: # если такой есть:
if product_to_delete.user_id == current_user.id: # если пользователь хочет удалить свой товар
# Удаляем объект из сессии и базы данных
product_to_delete.delete(product_id)
flash(message='Товар удален', category='success')
return redirect('/products')
else:
flash(message='Вы не можете удалить данный товар', category='warning')
else:
flash(message='Ошибка при удалении товара', category='danger')
else: # добавление товара
# Получаем данные из формы
name = request.form['name']
price = int(request.form['price'])
description = request.form['description']
# Создаем новый объект Product
new_product = Product()
new_product.name = name # добавляем в бд название товара
new_product.price = price # цену
new_product.description = description # описание
image = request.files['image']
if image:
# сохранение файла изображения в папке "uploads"
filename = secure_filename(image.filename)
image.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
new_product.image = filename
new_product.user_id = current_user.id # добавление в бд ид текущего пользователя
# Добавляем объект в сессию
db_sess.add(new_product)
# Сохраняем изменения в базе данных
db_sess.commit()
# Перенаправляем на главную страницу
return redirect('/products')
else:
# Получаем все продукты из базы данных
products = db_sess.query(Product).all()
# Отправляем данные на шаблон и рендерим страницу
return render_template('products.html', products=products)
@app.route('/products/sort', methods=['POST']) # сортировка на странице товаров
def sort_products():
products = None # нужно для передачи на страницу с продуктами (ну или же можно удалить)
sort_by = request.form['sort_by']
db_sess = db_session.create_session()
Product = data.products.Product
if sort_by == 'name': # сортировка по имени
products = db_sess.query(Product).order_by(Product.name)
elif sort_by == 'price': # по цене
products = db_sess.query(Product).order_by(Product.price)
return render_template('products.html', products=products)
@app.route('/delete_product/<int:product_id>', methods=['POST'])
# удаление товаров доступно для зарегистрированных пользователей, и удаление только того, что добавили они сами,
# поэтому конкретная функция для удаления
@login_required # нельзя удалить если не зареган
def delete_product(product_id):
Product = data.products.Product
db_sess = db_session.create_session()
product = db_sess.query(Product).get(product_id)
if product:
# Проверяем, соответствует ли текущий пользователь пользователю-владельцу товара
if product.user_id == current_user.id:
db_sess.delete(product)
db_sess.commit()
flash(message='Товар успешно удален', category='success')
else:
flash(message='Вы не можете удалить данный товар', category='warning')
else:
flash(message='Товар не найден', category='danger')
return redirect(url_for('products'))
@app.route('/contacts')
def contacts():
return render_template('contacts.html')
@app.route('/cart', methods=['POST', 'GET'])
def cart():
db_sess = db_session.create_session()
Cart = data.cart.Cart
if request.method == 'POST':
product_id = request.form['product_id']
add_to_cart(product_id)
flash(message='Товар добавлен в корзину', category='success')
return redirect(url_for('cart'))
else:
cart_items = db_sess.query(Cart).filter_by(user_id=current_user.id).all()
total = sum(item.price * item.quantity for item in cart_items)
return render_template('cart.html', items=cart_items, total=total, format_goods_count=format_goods_count)
@app.route("/add_to_cart/<int:product_id>", methods=["POST"])
@login_required
def add_to_cart(product_id, quantity=1):
# Получаем информацию о товаре из базы данных
db_sess = db_session.create_session()
Product = data.products.Product
Cart = data.cart.Cart
# Получаем информацию о товаре
cart_item = db_sess.query(Cart).filter_by(product_id=product_id, user_id=current_user.id).first()
if cart_item:
cart_item.quantity += quantity
db_sess.commit()
else:
product = db_sess.query(Product).filter_by(id=product_id).first()
# Проверяем, что такой товар существует
if product is not None:
# Добавляем товар в корзину
cart_item = Cart(product_id=product.id,
name=product.name,
user_id=current_user.id,
price=product.price,
quantity=1)
db_sess.add(cart_item)
db_sess.commit()
flash(message='Товар успешно добавлен в корзину!', category='product')
return redirect(url_for('product_detail', product_id=product_id))
@app.route('/delete_item/<int:item_id>')
def delete_item(item_id):
db_sess = db_session.create_session()
Product = data.products.Product
Cart = data.cart.Cart
item = db_sess.query(Cart).get(item_id)
if item.quantity > 1:
item.quantity -= 1
db_sess.commit()
else:
db_sess.delete(item)
db_sess.commit()
return redirect('/cart')
@app.route('/delete_all_items/<int:product_id>')
def delete_all_items(product_id):
db_sess = db_session.create_session()
Product = data.products.Product
Cart = data.cart.Cart
items = db_sess.query(Cart).filter_by(product_id=product_id, user_id=current_user.id).all()
for item in items:
db_sess.delete(item)
db_sess.commit()
return redirect('/cart')
@app.route('/delete_all_user_items')
def delete_all_user_items():
db_sess = db_session.create_session()
Product = data.products.Product
Cart = data.cart.Cart
items = db_sess.query(Cart).filter_by(user_id=current_user.id).all()
for item in items:
db_sess.delete(item)
db_sess.commit()
return redirect('/cart')
@app.route("/buy")
@login_required
def buy():
return render_template('buy.html')
@app.route("/products/<int:product_id>", methods=['POST', 'GET'])
def product_detail(product_id):
# Получаем информацию о товаре из базы данных
db_sess = db_session.create_session()
Product = data.products.Product
product = db_sess.query(Product).get(product_id)
# Отображаем шаблон с информацией о товаре
return render_template("product_detail.html", product=product)
@app.route("/checkout", methods=['POST', 'GET'])
def checkout():
return render_template('checkout.html')
@app.errorhandler(404) # обработчик 404
def not_found_error(error):
return render_template('404.html'), 404
def main():
db_session.global_init('products.db')
app.run(debug=True)
if __name__ == '__main__':
main()