我不知道如何在一个瓶子里分享会话

2024-04-24 11:31:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经修修补补了好几个小时了,但我似乎找不到一个办法来解决这个问题。看起来应该很简单,我肯定是的,但我被难住了。你知道吗

我有一个模块叫'服务器.py“这是处理瓶子的所有路径,这是执行的要点。请求处理程序的一个例子就是这样的,我的代码库相当庞大,大部分都与问题无关:

服务器.py

@route('home')
def home():
    page = Page('home') # A template manager I made
    objects = db.get_objects(10) # This is what I can't get to work

    return page.render(objects=objects)

我希望代码是从服务器端和所有的数据库交互中完成的简单双倍但是,使用helper函数时,我希望使用仍然附加到会话的查询返回的对象,因此它必须在外部关闭db.get\u对象. 每个请求都应该创建并关闭一个会话。我可以从home()手动完成,如下所示:

服务器.py

@route('home')
def home():
    session = Session()
    page = Page('home') # A jinja template manager I made
    objects = db.get_objects(session, 10)

    document = page.render(objects=objects)
    session.close()

    return document

我不介意每次打开和关闭会话,无论是直接还是通过另一个对象/函数,这似乎是逻辑和不可避免的,但我不想把会话(手动)传递给每个db helper函数,这对我来说似乎很混乱。你知道吗

我觉得这个问题可以用OOP、会话管理器类或者两者共享的东西来解决,但是我不知道如何设计或者共享它。到目前为止,我想到的最好的办法就是把我的整个双倍并让构造函数创建会话。这对helper函数很有用,但是我还有一堆其他的对象双倍它还需要访问会话,例如以下内容,这是我的代码库中的实际对象:

双倍

class Sticker(_Base):
    __tablename__ = 'sticker'
    sticker_id = Column(Integer, ForeignKey('product.product_id'), primary_key=True)
    sticker_name = Column(String)
    svg_location = Column(String, unique=True)
    svg_width = Column(Numeric, nullable=False)
    svg_height = Column(Numeric, nullable=False)
    shaped = Column(Boolean) # Whether the cutpath countors the image

    @reconstructor
    def _get_related_properties(self, init=False):
        '''Fetches and fills out all properties that are created by the
           __init__ constructor that are not in the orm constructor.'''
        if not init:
            session = Session()
            self._product = session.query(Product).filter(Product.product_id == self.sticker_id).first()
            category_id = session.query(ProductCategory).filter(ProductCategory.product_id == self.sticker_id).first()
            session.close()

        self.sticker_id = self._product.product_id
        self.product_type = self._product.product_type
        self.date_added = self._product.date_added
        self.sticker_name = self._product.product_name

    def _get_svg_size(self):
        """Returns a tuple of the width, height of an svg"""
        # Currently only works with pixels I think. I know it fails when saved as points.
        # May want to improve this for future versions.
        # May also consider moving this function to an external util file or something.
        # Possible units: (~"em" | ~"ex" | ~"px" | ~"in" | ~"cm" | ~"mm" | ~"pt" | ~"pc")
        # Also may use viewbox attribute to determine aspect ratio and set sizes algorithmically.
        import xml.etree.ElementTree as ET
        import decimal
        # Set decimal precision
        decimal.getcontext().prec=7
        tree = ET.parse(self.svg_location)
        root = tree.getroot()

        width = None
        height = None

        width_attr = root.get('width')
        height_attr = root.get('height')

        # Get measurement units
        units = width_attr[-2:]
        if units[-1] == '%':
            units = '%'
        elif not units.isalpha():
            # if units not set assume px
            width = decimal.Decimal(width_attr)
            height = decimal.Decimal(height_attr)
            units = 'px'

        if units != 'px':
            width = decimal.Decimal(width_attr[:-2])
            height = decimal.Decimal(height_attr[:-2])
            # Convert to px if not already
            # Currently only supports in, cm, mm, and pt
            # Assumes DPI is 72
            MMPI = 2.834645669291339
            DPI = 72

            if units == 'in':
                width *= DPI
                height *= DPI
            elif units == 'pt':
                width /= DPI
                height /= DPI
            elif units == 'mm':
                width *= MMPI
                height *= MMPI
            elif units == 'cm':
                width *= MMPI * 10
                height *= MMPI * 10
            else:
                raise ValueError('Unsupported svg size unit:',units )


        return width, height

    def __init__(self, svg_location, name='', category='', metatags=[], sticker_sizes=None, active=False):
        # If no name given use filename
        if not name:
            from os.path import basename
            name = basename(svg_location).rstrip('.svg')
        # Create parent product and save to db to generate primary key/product id
        session = Session()
        self._product = Product(product_name = name, product_type = 'sticker', active = active)
        session.add(self._product)
        session.commit()
        # TODO: Handle category and metatags
        # Categories should probably be created explicitly by the admin, and so should exist
        # at the time of sticker creation. Metatags are more numerous and created on the fly
        # and so should be created automatically by the sticker constructor.

        # TODO: Expand the sticker table to reference these values from the product table maybe?
        self.sticker_id = self._product.product_id
        self.svg_location = svg_location
        self.svg_width, self.svg_height = self._get_svg_size()
        self._get_related_properties(init=True)
        # Add to the Database
        session.add(self)
        session.commit()

        # Get sticker sizes
        self.sticker_sizes = []
        # Check if a size tuple was added, default is empty
        if sticker_sizes:
            for size in sticker_sizes:
                sticker_size = StickerSize(self.sticker_id, size[0], size[1])
                session.add(sticker_size)
                self.sticker_sizes.append(StickerSize)

        session.commit()
        session.close()

其中大部分并不重要,但正如您在许多情况下所看到的,我需要从ORM映射对象中查询数据库,以便它们也需要访问会话。所以一个简单的问题,我希望,我该怎么做?这是可以做到的,还是我用了错误的方法?如果我走错路了,你能提供一个可行的设计模式吗?你知道吗


Tags: thetonamesvgselfidsizeget
1条回答
网友
1楼 · 发布于 2024-04-24 11:31:14

我找到了一个解决方案,那就是将会话附加到request对象,很明显,这个对象对于每个请求都是唯一的,并且可以在模块之间共享。你知道吗

相关问题 更多 >