简体   繁体   中英

Plone/Sqlalchemy (saconfig) - Using .filter of a session object, how can I filter on specific fields that were chosen by a user?

I have mapped fields defined in an Interface to a mysql backend database through the use of saconfig and a declarative base.* On my Plone Site instance, I have a form (z3c.form) that will use these fields and will be used to search for "Assets" from a mysql database based on criteria entered in several fields. In my case, I would like to only query on fields that have data entered in them.

This is what my interface and ORMBase class look like:

class IAsset(Interface):
    """Interface class of an asset
    """

    Asset_ID = schema.Int(title=u"Asset ID",
                          required=False
                         )

    GPCL_Asset_ID = schema.TextLine(title=u"GPCL Asset Tracker",
                                    required=False
                                   )

    Asset_Type = schema.Int(title=u"Asset Type",
                        required=False
                       )

    Manufacturer = schema.Int(title=u"Manufacturer",
                          required=True
                         )
    Model = schema.TextLine(title=u"Serial Number",
                            required=False
                           )
    Serial_Number = schema.TextLine(title=u"Serial Number",
                                required=False
                               )


class Asset(ORMBase):
    """Class for asset
    """
    __tablename__ = 'Assets'

    Asset_ID = sqlalchemy.Column(sqlalchemy.Integer(),
                                 primary_key=True,
                                 autoincrement=True
                                )
    GPCL_Asset_ID = sqlalchemy.Column(sqlalchemy.String(255),
                                      nullable=True
                                     )

    Asset_Type = sqlalchemy.Column(sqlalchemy.Integer(),
                                   nullable=False
                                  )

    Manufacturer = sqlalchemy.Column(sqlalchemy.Integer(),
                                 nullable=False
                                )

    Model = sqlalchemy.Column(sqlalchemy.String(255),
                              nullable=True
                             )

    Serial_Number = sqlalchemy.Column(sqlalchemy.String(255),
                                      nullable=True
                                     )

For testing purposes, I am using the view class of an Asset, and I have a function (current called through a template for testing purposes) that builds a dictionary based on fields that are filled out. I also have a utility class called AssetUtils and there is a function in the class called queryAssets that accepts a dictionary containing the criteria, and returns the search results found.

class View(grok.View):
    """View class
    """
    ...grok definitions and fields being set for form


    def searchAssets(self):
        #get data
        ....

        criteria = {}
        #build dictionary
        #if field (i.e. GPCL_Asset_ID) is not empty, add to the dictionary GPCL_Asset_ID:valueEnteredByUser

        assets = queryAssets(criteria)


class AssetUtils(grok.GlobalUtility):
    def queryAssets(searchCriteria):

I have a session object defined at the root of the class. In queryAssets I would like to use session.query(Asset).filter() to query the Assets table. The problem I am having though is figuring out what to pass into filter(). I know how to use the query function, like session.query(Asset).filter(GPCL_Asset_ID.like('D%'),Manufacturer==15). However, say Serial Number was present, but GPCL_Asset_ID was not, so I would like to use .filter(Serial_Number.like("EX12%")), and then another case where only Model and Manufacturer were present. .filter(Model.like("A3%"),Manufacturer==32)

So my question is, how can I make it so that .filter filters on fields that were defined/chosen in the dictionary passed into the queryAssets function I have, as opposed to fields being pre-defined in the .filter function?

*I am following along with the book "Professional Plone 4 Development" by Martin Aspeli, chapter 12 and a slideshow presentation ( http://www.slideshare.net/jbellis/pycon-2010-sqlalchemy-tutorial ) - Slide 27, 29. Compared to the slideshow, I am actually using saconfig as found in Martin Aspeli's book.

Looking at your class, from the searchAssets method you simply need to access the self.request.form dict-like object and read all the data submitted (by HTTP GET or POST) to that view.

You can then build your list of filters parameters like:

params = []
if 'param1' in self.request.form:
    params.append(Asset_ID.like(...))
if ...

session.query(*params)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM