feat: image upload on product
This commit is contained in:
		@@ -15,4 +15,4 @@ PG_HOST = os.environ.get('PG_HOST')
 | 
				
			|||||||
TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')
 | 
					TELEGRAM_BOT_TOKEN = os.environ.get('TELEGRAM_BOT_TOKEN')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SECRET_KEY = os.environ.get('SECRET_KEY')
 | 
					SECRET_KEY = os.environ.get('SECRET_KEY')
 | 
				
			||||||
S3_API_KEY = '1cc46590-4532-4046-97aa-baf3e49f20ad-AUF'
 | 
					S3_API_KEY = os.environ.get('S3_API_KEY')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -26,7 +26,7 @@ class Product(BaseModel):
 | 
				
			|||||||
    additional_info = Column(String, nullable=True, comment='Дополнительное поле')
 | 
					    additional_info = Column(String, nullable=True, comment='Дополнительное поле')
 | 
				
			||||||
    images = relationship('ProductImage',
 | 
					    images = relationship('ProductImage',
 | 
				
			||||||
                          back_populates='product',
 | 
					                          back_populates='product',
 | 
				
			||||||
 | 
					                          lazy='selectin',
 | 
				
			||||||
                          cascade="all, delete-orphan")
 | 
					                          cascade="all, delete-orphan")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,17 @@
 | 
				
			|||||||
from typing import List
 | 
					from typing import List
 | 
				
			||||||
from schemas.barcode import BarcodeTemplateSchema
 | 
					from schemas.barcode import BarcodeTemplateSchema
 | 
				
			||||||
from schemas.base import CustomModelCamel, PaginationInfoSchema, OkMessageSchema
 | 
					from schemas.base import CustomModelCamel, PaginationInfoSchema, OkMessageSchema
 | 
				
			||||||
from pydantic import field_validator
 | 
					from pydantic import field_validator, model_validator
 | 
				
			||||||
from models import ProductBarcode
 | 
					from models import ProductBarcode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# region Entities
 | 
					# region Entities
 | 
				
			||||||
 | 
					class ProductImageSchema(CustomModelCamel):
 | 
				
			||||||
 | 
					    id: int
 | 
				
			||||||
 | 
					    product_id: int
 | 
				
			||||||
 | 
					    image_url: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BaseProductSchema(CustomModelCamel):
 | 
					class BaseProductSchema(CustomModelCamel):
 | 
				
			||||||
    name: str
 | 
					    name: str
 | 
				
			||||||
    article: str | None = ''
 | 
					    article: str | None = ''
 | 
				
			||||||
@@ -19,6 +25,8 @@ class BaseProductSchema(CustomModelCamel):
 | 
				
			|||||||
    composition: str | None = None
 | 
					    composition: str | None = None
 | 
				
			||||||
    size: str | None = None
 | 
					    size: str | None = None
 | 
				
			||||||
    additional_info: str | None = None
 | 
					    additional_info: str | None = None
 | 
				
			||||||
 | 
					    image_url: str | None = None
 | 
				
			||||||
 | 
					    images: list[ProductImageSchema]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @field_validator('barcodes', mode="before")
 | 
					    @field_validator('barcodes', mode="before")
 | 
				
			||||||
    def barcodes_to_list(cls, v):
 | 
					    def barcodes_to_list(cls, v):
 | 
				
			||||||
@@ -26,6 +34,15 @@ class BaseProductSchema(CustomModelCamel):
 | 
				
			|||||||
            return [barcode.barcode for barcode in v]
 | 
					            return [barcode.barcode for barcode in v]
 | 
				
			||||||
        return v
 | 
					        return v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @model_validator(mode="after")
 | 
				
			||||||
 | 
					    def image_url_to_list(cls, values):
 | 
				
			||||||
 | 
					        images = values.images
 | 
				
			||||||
 | 
					        if not images:
 | 
				
			||||||
 | 
					            return values
 | 
				
			||||||
 | 
					        latest_image = images[-1]
 | 
				
			||||||
 | 
					        values.image_url = latest_image.image_url
 | 
				
			||||||
 | 
					        return values
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProductSchema(BaseProductSchema):
 | 
					class ProductSchema(BaseProductSchema):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -67,6 +67,8 @@ class ProductService(BaseService):
 | 
				
			|||||||
        del product_dict['id']
 | 
					        del product_dict['id']
 | 
				
			||||||
        del product_dict['barcodes']
 | 
					        del product_dict['barcodes']
 | 
				
			||||||
        del product_dict['barcode_template']
 | 
					        del product_dict['barcode_template']
 | 
				
			||||||
 | 
					        del product_dict['image_url']
 | 
				
			||||||
 | 
					        del product_dict['images']
 | 
				
			||||||
        if request.product.barcode_template:
 | 
					        if request.product.barcode_template:
 | 
				
			||||||
            product_dict['barcode_template_id'] = request.product.barcode_template.id
 | 
					            product_dict['barcode_template_id'] = request.product.barcode_template.id
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,9 +152,12 @@ class ProductService(BaseService):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    async def upload_image(self, product_id: int, file_bytes: bytes) -> ProductUploadImageResponse:
 | 
					    async def upload_image(self, product_id: int, file_bytes: bytes) -> ProductUploadImageResponse:
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            product = await self.get_by_id(product_id)
 | 
					            product: Product = await self.session.get(Product, product_id)
 | 
				
			||||||
            if not product:
 | 
					            if not product:
 | 
				
			||||||
                raise Exception("Неудалось найти товар с указанным ID")
 | 
					                raise Exception("Неудалось найти товар с указанным ID")
 | 
				
			||||||
 | 
					            # removing previous images
 | 
				
			||||||
 | 
					            for image in product.images:
 | 
				
			||||||
 | 
					                await self.session.delete(image)
 | 
				
			||||||
            s3_uploader = S3Uploader(config.S3_API_KEY)
 | 
					            s3_uploader = S3Uploader(config.S3_API_KEY)
 | 
				
			||||||
            response = await s3_uploader.upload(file_bytes)
 | 
					            response = await s3_uploader.upload(file_bytes)
 | 
				
			||||||
            response_url = response.get('link')
 | 
					            response_url = response.get('link')
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user