Понад 2000 продуктів

Кількісні знижки

5% знижки

На перше замовлення

ALLBAGWITA
Показати як

Worki materiałowe z nadrukiem

Матеріали для друку Тканинні мішки з друком

(Продукти 12)
Візерункові бавовняні сумки з власною друкованою розписом не лише зручні, але й відмінний засіб для реклами. Це чудовий спосіб виділитися та просувати власну марку. +++++ yourapp.py import os import sys from flask import Flask, request, jsonify, render_template from flask_cors import CORS from werkzeug.utils import secure_filename import uuid import json import requests from datetime import datetime import logging from logging.handlers import RotatingFileHandler from flask_sqlalchemy import SQLAlchemy from sqlalchemy import text from sqlalchemy.exc import SQLAlchemyError import hashlib import base64 import re from flask_mail import Mail, Message from flask_migrate import Migrate from flask_caching import Cache from flask_limiter import Limiter from flask_limiter.util import get_remote_address from flask_jwt_extended import JWTManager, jwt_required, create_access_token, get_jwt_identity from flask_bcrypt import Bcrypt from flask_restful import Api, Resource from flask_restful_swagger import swagger from flask_restful_swagger.ui import SwaggerUI from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import swagger_from_file from flask_restful_swagger import swagger_from_dict from flask_restful_swagger import Swagger # Remove duplicate imports from flask_restful_swagger import swagger_from_file, swagger_from_dict, Swagger app = Flask(__name__) app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'your-secret-key-here') app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///app.db') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['UPLOAD_FOLDER'] = 'uploads' app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB app.config['MAIL_SERVER'] = os.getenv('MAIL_SERVER', 'smtp.example.com') app.config['MAIL_PORT'] = int(os.getenv('MAIL_PORT', 587)) app.config['MAIL_USE_TLS'] = os.getenv('MAIL_USE_TLS', 'true').lower() == 'true' app.config['MAIL_USERNAME'] = os.getenv('MAIL_USERNAME') app.config['MAIL_PASSWORD'] = os.getenv('MAIL_PASSWORD') app.config['MAIL_DEFAULT_SENDER'] = os.getenv('MAIL_DEFAULT_SENDER') app.config['CACHE_TYPE'] = 'SimpleCache' app.config['CACHE_DEFAULT_TIMEOUT'] = 300 app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY', 'jwt-secret-key-here') app.config['JWT_ACCESS_TOKEN_EXPIRES'] = int(os.getenv('JWT_ACCESS_TOKEN_EXPIRES', 3600)) # Initialize extensions db = SQLAlchemy(app) mail = Mail(app) bcrypt = Bcrypt(app) jwt = JWTManager(app) migrate = Migrate(app, db) limiter = Limiter( app=app, key_func=get_remote_address, default_limits=["200 per day", "50 per hour"] ) cache = Cache(app) api = Api(app) swagger = Swagger(app) # Configure logging if not os.path.exists('logs'): os.makedirs('logs') handler = RotatingFileHandler('logs/app.log', maxBytes=10000, backupCount=3) handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) app.logger.addHandler(handler) # Create uploads directory if it doesn't exist if not os.path.exists(app.config['UPLOAD_FOLDER']): os.makedirs(app.config['UPLOAD_FOLDER']) # Database models class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password_hash = db.Column(db.String(128), nullable=False) first_name = db.Column(db.String(50)) last_name = db.Column(db.String(50)) role = db.Column(db.String(20), default='user') is_active = db.Column(db.Boolean, default=True) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) def set_password(self, password): self.password_hash = bcrypt.generate_password_hash(password).decode('utf-8') def check_password(self, password): return bcrypt.check_password_hash(self.password_hash, password) class Product(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) description = db.Column(db.Text) price = db.Column(db.Float, nullable=False) stock = db.Column(db.Integer, default=0) category_id = db.Column(db.Integer, db.ForeignKey('category.id')) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) images = db.relationship('ProductImage', backref='product', lazy=True) customizations = db.relationship('ProductCustomization', backref='product', lazy=True) class Category(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(50), nullable=False) description = db.Column(db.Text) parent_id = db.Column(db.Integer, db.ForeignKey('category.id')) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) products = db.relationship('Product', backref='category', lazy=True) class ProductImage(db.Model): id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False) image_path = db.Column(db.String(255), nullable=False) is_primary = db.Column(db.Boolean, default=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class ProductCustomization(db.Model): id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False) customization_type = db.Column(db.String(50), nullable=False) options = db.Column(db.JSON, nullable=False) price_addition = db.Column(db.Float, default=0.0) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Order(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) status = db.Column(db.String(20), default='pending') total_amount = db.Column(db.Float, nullable=False) shipping_address = db.Column(db.Text, nullable=False) billing_address = db.Column(db.Text, nullable=False) payment_method = db.Column(db.String(50)) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) items = db.relationship('OrderItem', backref='order', lazy=True) class OrderItem(db.Model): id = db.Column(db.Integer, primary_key=True) order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False) product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False) quantity = db.Column(db.Integer, default=1) customization_data = db.Column(db.JSON) unit_price = db.Column(db.Float, nullable=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) class Review(db.Model): id = db.Column(db.Integer, primary_key=True) product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) rating = db.Column(db.Integer, nullable=False) comment = db.Column(db.Text) created_at = db.Column(db.DateTime, default=datetime.utcnow) updated_at = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow) class Notification(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) type = db.Column(db.String(50), nullable=False) message = db.Column(db.Text, nullable=False) is_read = db.Column(db.Boolean, default=False) created_at = db.Column(db.DateTime, default=datetime.utcnow) # Helper functions def generate_unique_filename(filename): ext = os.path.splitext(filename)[1] unique_id = str(uuid.uuid4())[:8] return f"{unique_id}{ext}" def send_email(subject, recipients, html_body, text_body=None): msg = Message(subject, recipients=recipients) msg.body = text_body msg.html = html_body try: mail.send(msg) return True except Exception as e: app.logger.error(f"Failed to send email: {str(e)}") return False def validate_email(email): pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' return re.match(pattern, email) is not None def validate_password(password): if len(password) < 8: return False if not re.search(r'[A-Z]', password): return False if not re.search(r'[a-z]', password): return False if not re.search(r'[0-9]', password): return False if not re.search(r'[!@#$%^&*(),.?":{}|<>]', password): return False return True def create_access_token(user_id): return create_access_token(identity=user_id) # API Resources class UserResource(Resource): @jwt_required() def get(self): current_user_id = get_jwt_identity() user = User.query.get(current_user_id) if not user: return {'message': 'User not found'}, 404 return { 'id': user.id, 'username': user.username, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'role': user.role, 'is_active': user.is_active, 'created_at': user.created_at.isoformat(), 'updated_at': user.updated_at.isoformat() } @jwt_required() def put(self): current_user_id = get_jwt_identity() data = request.get_json() user = User.query.get(current_user_id) if not user: return {'message': 'User not found'}, 404 if 'password' in data: if not validate_password(data['password']): return {'message': 'Invalid password format'}, 400 user.set_password(data['password']) if 'username' in data: user.username = data['username'] if 'email' in data: if not validate_email(data['email']): return {'message': 'Invalid email format'}, 400 user.email = data['email'] if 'first_name' in data: user.first_name = data['first_name'] if 'last_name' in data: user.last_name = data['last_name'] db.session.commit() return { 'message': 'User updated successfully', 'user': { 'id': user.id, 'username': user.username, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'role': user.role, 'is_active': user.is_active, 'created_at': user.created_at.isoformat(), 'updated_at': user.updated_at.isoformat() } } class LoginResource(Resource): def post(self): data = request.get_json() email = data.get('email') password = data.get('password') if not email or not password: return {'message': 'Email and password are required'}, 400 user = User.query.filter_by(email=email).first() if not user or not user.check_password(password): return {'message': 'Invalid email or password'}, 401 access_token = create_access_token(identity=user.id) return { 'access_token': access_token, 'token_type': 'bearer', 'user': { 'id': user.id, 'username': user.username, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'role': user.role, 'is_active': user.is_active } } class RegisterResource(Resource): def post(self): data = request.get_json() if not data or not all(key in data for key in ['username', 'email', 'password']): return {'message': 'Username, email and password are required'}, 400 if not validate_email(data['email']): return {'message': 'Invalid email format'}, 400 if not validate_password(data['password']): return {'message': 'Password must be at least 8 characters long and contain at least one uppercase letter, one lowercase letter, one number and one special character'}, 400 if User.query.filter_by(username=data['username']).first(): return {'message': 'Username already exists'}, 409 if User.query.filter_by(email=data['email']).first(): return {'message': 'Email already exists'}, 409 user = User( username=data['username'], email=data['email'], first_name=data.get('first_name', ''), last_name=data.get('last_name', ''), role='user' ) user.set_password(data['password']) try: db.session.add(user) db.session.commit() # Send welcome email welcome_subject = "Welcome to Our Platform" welcome_body = f"""

Welcome, {data['username']}!

Thank you for registering with our platform.

Your account has been successfully created.

""" send_email(welcome_subject, [data['email']], welcome_body) return { 'message': 'User registered successfully', 'user': { 'id': user.id, 'username': user.username, 'email': user.email, 'first_name': user.first_name, 'last_name': user.last_name, 'role': user.role } } except SQLAlchemyError as e: db.session.rollback() app.logger.error(f"Registration failed: {str(e)}") return {'message': 'Registration failed'}, 500 # Add resources to API api.add_resource(UserResource, '/api/users/me') api.add_resource(LoginResource, '/api/auth/login') api.add_resource(RegisterResource, '/api/auth/register') # Routes @app.route('/') def index(): return render_template('index.html') @app.route('/api/products') def get_products(): products = Product.query.all() return jsonify([{ 'id': product.id, 'name': product.name, 'description': product.description, 'price': product.price, 'stock': product.stock, 'category': product.category.name if product.category else None, 'created_at': product.created_at.isoformat(), 'updated_at': product.updated_at.isoformat(), 'images': [image.image_path for image in product.images] } for product in products]) @app.route('/api/products/') def get_product(product_id): product = Product.query.get(product_id) if not product: return {'message': 'Product not found'}, 404 return { 'id': product.id, 'name': product.name, 'description': product.description, 'price': product.price, 'stock': product.stock, 'category': product.category.name if product.category else None, 'created_at': product.created_at.isoformat(), 'updated_at': product.updated_at.isoformat(), 'images': [image.image_path for image in product.images], 'customizations': [{ 'id': customization.id, 'type': customization.customization_type, 'options': customization.options, 'price_addition': customization.price_addition } for customization in product.customizations] } @app.route('/api/upload', methods=['POST']) @jwt_required() @limiter.limit("5 per minute") def upload_file(): if 'file' not in request.files: return {'message': 'No file part'}, 400 file = request.files['file'] if file.filename == '': return {'message': 'No selected file'}, 400 if file: filename = generate_unique_filename(file.filename) filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save(filepath) return { 'message': 'File uploaded successfully', 'filename': filename, 'filepath': filepath } @app.route('/api/health') def health_check(): return jsonify({'status': 'healthy'}) # Error handlers @app.errorhandler(404) def not_found(error): return jsonify({'message': 'Resource not found'}), 404 @app.errorhandler(500) def internal_error(error): return jsonify({'message': 'Internal server error'}), 500 # JWT error handlers @jwt.expired_token_loader def expired_token_callback(expired_token): return jsonify({ 'message': 'The token has expired', 'expired_token': expired_token }), 401 @jwt.invalid_token_loader def invalid_token_callback(error): return jsonify({ 'message': 'Invalid token', 'error': str(error) }), 401 @jwt.unauthorized_loader def unauthorized_callback(error): return jsonify({ 'message': 'Authorization required', 'error': str(error) }), 401 # Cache control @app.after_request def after_request(response): cache_control = 'public, max-age=0' if request.path.startswith('/api'): cache_control = 'private, max-age=0' response.headers['Cache-Control'] = cache_control return response if __name__ == '__main__': app.run(debug=True)

Матеріали для друку Тканинні мішки з друком Колекція

Porównaj /3

Завантаження...
//