Jump to content

select and rename in a query


pawel

Recommended Posts

hi,

is it possible to rename (like in sql) fetched columns in a query?

session.query('select first_name as firstName, last_name as lastName from User where email is "bla@dot.com"')

or some other way to rename fetched keys?

I'm trying to port our current system to ftrack. It expects certain attributes on a fetched user object. I can fairly easily remap all the attributes in python but this will be double handling the hardcoded names and will lead to easy mistakes and issues. Ideally, I would like to do the renaming in the query where all the attribute names are hardcoded. Or alternatively somewhere in the ftrack web interface (without using custom attributes for everything).

thank you.

Link to comment
Share on other sites

thank you Lucas.

do you have an example of customized entity that renames attributes? I tried just adding a new attribute and setting it's value but my knowledge of the API is not extensive enough to do so. my crude implementation:

logging.basicConfig(level=logging.DEBUG)


class Factory(ftrack_api.entity.factory.StandardFactory):
    '''Entity class factory.'''

    def create(self, schema, bases=None):
        '''Create and return entity class from *schema*.'''
        # Optionally change bases for class to be generated.
        cls = super(Factory, self).create(schema, bases=bases)

        if str(schema['id']) == 'User':
            print "replacing User class"
            cls.default_projections = ['id', 'username', 'first_name', 'last_name']
            a = ftrack_api.attribute.Attribute('firstName')
            cls.attributes.add(a)

            a.set_local_value(cls, 'foobar')

        return cls

he above fails on `set_local_value` as it is missing session context. Probably adding an attribute is not the way it should be done. I also tried a full implementation of User sub class with custom  `__getitem__` etc but that quickly become a bit problematic...

renaming attributes must be a very common practice and I'm sure you have a nice solution for it. 

cheers.

Link to comment
Share on other sites

Hi Pawel,

below is one possible solution, overriding the __getitem__ and __setitem__ methods,  you mentioned you ran into issues overriding these methods, so sorry if there is something I have overlooked and if so please let me know what issues those were.

import ftrack_api

class CustomUser(ftrack_api.entity.base.Entity):
    custom_mapping = {
        'firstName': 'first_name',
        'lastName': 'last_name'
    }


    def __getitem__(self, key):
        if key in self.custom_mapping:
            key = self.custom_mapping[key]

        return super(CustomUser, self).__getitem__(key)


    def __setitem__(self, key, value):
        if key in self.custom_mapping:
            key = self.custom_mapping[key]

        return super(CustomUser, self).__setitem__(key, value)


class Factory(ftrack_api.entity.factory.StandardFactory):
    '''Entity class factory.'''

    def create(self, schema, bases=None):
        '''Create and return entity class from *schema*.'''
        # Optionally change bases for class to be generated.

        if schema['id'] in ('User',):
            bases = [CustomUser]

        cls = super(Factory, self).create(
                schema, bases=bases
        )

        return cls

 

cheers

Eric

Link to comment
Share on other sites

thank you Eric.

Let me rephrase. I didn't run into problems overriding those methods but quickly realised I will need to override many more than just those two.  Like *keys* and *items* and *__contains__* and basically almost everything that gets inherited from *collection* which is the base class of everything. If I don't do that many simple things break, for instance:

#user = CustomUser returned by the api
if key in user:
	#do something

will not work if I only override __getitem__

I was hoping for some solution already built into Atrribute or AttributeCollection but by browsing the code base I don't think there is any.

thank you. appreciate your help.

Link to comment
Share on other sites

Hi Pawel, a potential workaround would be to implement a "proxy" attribute type, please keep in mind that this is more of a proof of concept and I have done very limited testing

It would have solve the keys, items and contains cases you mentioned, it might still be confusing when using projections during queries as the attributes will then have there "incorrect" names.

import ftrack_api


class ProxyAttribute(object):
    def __init__(self, name, attribute):
        self.name = name
        self.__proxy_attribute = attribute

        super(ProxyAttribute, self).__init__()

    def __getattribute__(self, attr):
        if attr.startswith('__') or attr in self.__dict__:
            try:
                return object.__getattribute__(
                    self, attr
                )
            except AttributeError:
                raise

        return object.__getattribute__(
            self.__proxy_attribute, attr
        )


class Factory(ftrack_api.entity.factory.StandardFactory):
    user_custom_mapping = {
        'first_name': 'firstName',
        'last_name': 'lastName'
    }

    def create(self, schema, bases=None):
        cls = super(Factory, self).create(
            schema, bases=bases
        )

        if schema['id'] in ('User', ):
            for attribute_name, alias in self.user_custom_mapping.items():
                cls.attributes.add(
                    ProxyAttribute(alias, cls.attributes.get(attribute_name))
                )

        return cls

 

cheers

Eric

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...