[pricelist] Use new image controller

This commit is contained in:
Ferdinand Thiessen 2021-11-15 16:34:35 +01:00
parent a6fe921920
commit a43441e0c5
5 changed files with 25 additions and 103 deletions

View File

@ -2,10 +2,11 @@
from flask import Blueprint, jsonify, request, current_app
from werkzeug.local import LocalProxy
from werkzeug.exceptions import BadRequest, Forbidden, Unauthorized
from werkzeug.exceptions import BadRequest, Forbidden, NotFound, Unauthorized
from flaschengeist import logger
from flaschengeist.controller import userController
from flaschengeist.controller.imageController import send_image, send_thumbnail
from flaschengeist.plugins import Plugin
from flaschengeist.utils.decorators import login_required, extract_session
from flaschengeist.utils.HTTP import no_content
@ -709,7 +710,7 @@ def get_priclist_setting(userid, current_session):
return no_content()
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>/picture", methods=["POST", "GET", "DELETE"])
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>/picture", methods=["POST" "DELETE"])
@login_required(permission=permissions.EDIT)
def set_picture(identifier, current_session):
"""Get, Create, Delete Drink Picture
@ -731,25 +732,24 @@ def set_picture(identifier, current_session):
file = request.files.get("file")
if file:
picture = models._Picture()
picture.mimetype = file.content_type
picture.binary = bytearray(file.stream.read())
return jsonify(pricelist_controller.save_drink_picture(identifier, picture))
return jsonify(pricelist_controller.save_drink_picture(identifier, file))
else:
raise BadRequest
@PriceListPlugin.blueprint.route("/picture/<identifier>", methods=["GET"])
@PriceListPlugin.blueprint.route("/drinks/<int:identifier>/picture", methods=["GET"])
def _get_picture(identifier):
"""Get Picture
Args:
identifier: Identifier of Picture
identifier: Identifier of Drink
Returns:
Picture or HTTP-error
"""
if request.method == "GET":
size = request.args.get("size")
response = pricelist_controller.get_drink_picture(identifier, size)
return response.make_conditional(request)
drink = pricelist_controller.get_drink(identifier)
if drink.has_image:
if request.args.get("thumbnail"):
return send_thumbnail(image=drink.image_)
return send_image(image=drink.image_)
raise NotFound

View File

@ -1,7 +1,7 @@
from __future__ import annotations # TODO: Remove if python requirement is >= 3.10
from flaschengeist.database import db
from flaschengeist.models import ModelSerializeMixin
from flaschengeist.models.image import Image
from typing import Optional
@ -150,11 +150,14 @@ class Drink(db.Model, ModelSerializeMixin):
volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=2, asdecimal=False))
cost_per_volume: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
cost_per_package: Optional[float] = db.Column(db.Numeric(precision=5, scale=3, asdecimal=False))
has_image: bool = False
uuid: str = db.Column(db.String(36))
receipt: Optional[list[str]] = db.Column(db.PickleType(protocol=4))
_type_id = db.Column("type_id", db.Integer, db.ForeignKey("drink_type.id"))
_image_id = db.Column("image_id", Serial, db.ForeignKey("image.id"))
image_: Image = db.relationship("Image", cascade="all, delete", foreign_keys=[_image_id])
tags: Optional[list[Tag]] = db.relationship("Tag", secondary=drink_tag_association, cascade="save-update, merge")
type: Optional[DrinkType] = db.relationship("DrinkType", foreign_keys=[_type_id])
@ -166,9 +169,6 @@ class Drink(db.Model, ModelSerializeMixin):
def __repr__(self):
return f"Drink({self.id},{self.name},{self.volumes})"
class _Picture:
"""Wrapper class for pictures binaries"""
mimetype = ""
binary = bytearray()
@property
def has_image(self):
return self.image_ is not None

View File

@ -5,12 +5,12 @@ from uuid import uuid4
from flaschengeist import logger
from flaschengeist.config import config
from flaschengeist.database import db
from flaschengeist.utils.picture import save_picture, get_picture, delete_picture
from flaschengeist.utils.decorators import extract_session
from .models import Drink, DrinkPrice, Ingredient, Tag, DrinkType, DrinkPriceVolume, DrinkIngredient, ExtraIngredient
from .permissions import EDIT_VOLUME, EDIT_PRICE, EDIT_INGREDIENTS_DRINK
import flaschengeist.controller.imageController as image_controller
def update():
db.session.commit()
@ -333,9 +333,6 @@ def set_volumes(volumes):
def delete_drink(identifier):
drink = get_drink(identifier)
if drink.uuid:
path = config["pricelist"]["path"]
delete_picture(f"{path}/{drink.uuid}")
db.session.delete(drink)
db.session.commit()
@ -534,33 +531,13 @@ def delete_extra_ingredient(identifier):
def save_drink_picture(identifier, file):
drink = get_drink(identifier)
old_uuid = None
if drink.uuid:
old_uuid = drink.uuid
drink.uuid = str(uuid4())
drink.image = image_controller.upload_image(file)
db.session.commit()
path = config["pricelist"]["path"]
save_picture(file, f"{path}/{drink.uuid}")
if old_uuid:
delete_picture(f"{path}/{old_uuid}")
return drink
def get_drink_picture(identifier, size=None):
path = config["pricelist"]["path"]
drink = None
if isinstance(identifier, int):
drink = get_drink(identifier)
if isinstance(identifier, str):
drink = Drink.query.filter(Drink.uuid == identifier).one_or_none()
if drink:
return get_picture(f"{path}/{drink.uuid}", size)
raise FileNotFoundError
def delete_drink_picture(identifier):
drink = get_drink(identifier)
if drink.uuid:
delete_picture(f"{config['pricelist']['path']}/{drink.uuid}")
drink.uuid = None
db.session.commit()
drink.image = None
db.session.commit()
return drink

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View File

@ -1,55 +0,0 @@
import os, sys, shutil, io
from PIL import Image
from flask import Response
from werkzeug.exceptions import BadRequest
from ..utils.HTTP import no_content
thumbnail_sizes = ((32, 32), (64, 64), (128, 128), (256, 256), (512, 512))
def save_picture(picture, path):
if not picture.mimetype.startswith("image/"):
raise BadRequest
os.makedirs(path, exist_ok=True)
file_type = picture.mimetype.replace("image/", "")
filename = f"{path}/drink"
with open(f"{filename}.{file_type}", "wb") as file:
file.write(picture.binary)
image = Image.open(f"{filename}.{file_type}")
if file_type != "png":
image.save(f"{filename}.png", "PNG")
os.remove(f"{filename}.{file_type}")
for thumbnail_size in thumbnail_sizes:
work_image = image.copy()
work_image.thumbnail(thumbnail_size)
work_image.save(f"{filename}-{thumbnail_size[0]}.png", "PNG")
def get_picture(path, size=None):
try:
if size:
if os.path.isfile(f"{path}/drink-{size}.png"):
with open(f"{path}/drink-{size}.png", "rb") as file:
image = file.read()
else:
_image = Image.open(f"{path}/drink.png")
_image.thumbnail((int(size), int(size)))
with io.BytesIO() as file:
_image.save(file, format="PNG")
image = file.getvalue()
else:
with open(f"{path}/drink.png", "rb") as file:
image = file.read()
response = Response(image, mimetype="image/png")
response.add_etag()
return response
except:
raise FileNotFoundError
def delete_picture(path):
try:
shutil.rmtree(path)
except FileNotFoundError:
pass