La consulta ftrack es un envoltorio orientado a objetos sobre la API FTRack. Si bien la sintaxis de consulta predeterminada es poderosa, se basa completamente en texto para que las consultas dinámicas puedan ser difíciles de construir. Este módulo admite y / u operadores con comparaciones anidadas.
Se recomienda leer por primera vez https://ftrack-python-api.readthedocs.io/en/stable/tutorial.html para una comprensión básica de cómo funciona la API FTRack.
pip install ftrack_query
En lugar de escribir toda la cadena de consulta a la vez, se construye una "declaración" ( por ejemplo, stmt = select('Task') ), y la consulta se puede construir llamando métodos tales como .where() y .populate() en la declaración.
Todos los métodos CRUD son compatibles ( create , select , update , delete ), pero la funcionalidad principal está diseñada para usar con select . Las declaraciones se construyen con una sintaxis similar a la API principal, por lo que debe ser sencilla transición entre los dos.
Tenga en cuenta que esto es completamente compatible hacia atrás, por lo que las consultas existentes no necesitan ser reescritas.
El siguiente ejemplo es para consultas muy básicas:
from ftrack_query import FTrackQuery , attr , create , select , and_ , or_
with FTrackQuery () as session :
# Select
project = session . select ( 'Project' ). where ( name = 'Test Project' ). one ()
# Create
task = session . execute (
create ( 'Task' ). values (
name = 'My Task' ,
project = project ,
)
)
session . commit ()
# Update
rows_updated = session . execute (
update ( 'Task' )
. where ( name = 'Old Task Name' )
. values ( name = 'New Task Name' )
)
session . commit ()
# Delete
rows_deleted = session . execute (
delete ( 'Task' ). where (
name = 'Old Task Name' ,
)
)
session . commit ()Para un ejemplo mucho más complejo:
ATTR_TYPE = attr ( 'type.name' )
TASK_STMT = (
select ( 'Task' )
# Filter the tasks
. where (
# Get any task without these statuses
~ attr ( 'status.name' ). in_ ([ 'Lighting' , 'Rendering' ]),
# Check for notes matching any of the following conditions:
attr ( 'notes' ). any (
# Ensure note was posted by someone outside the company
~ attr ( 'user.email' ). endswith ( '@company.com' )
# Ensure note either not completable or not completed
or_ (
and_ (
completed_by = None ,
is_todo = True ,
),
is_todo = False ,
),
),
# Ensure it has an animation task
or_ (
ATTR_TYPE . contains ( 'Animation' ),
ATTR_TYPE == 'Anim_Fixes' ,
),
),
# Order the results
. order_by (
ATTR_TYPE . desc (), # Equivalent to "type.name desc"
'name' ,
)
# Use projections to populate attributes as part of the query
. populate (
'name' ,
'notes' ,
'status.name' ,
ATTR_TYPE ,
)
. limit ( 5 )
)
with FTrackQuery () as session :
# Filter the above query to the result of another query
task_stmt = TASK_STMT . where (
project_id = session . select ( 'Project' ). where ( name = 'Test Project' ). one ()[ 'id' ]
)
# Use the current session to execute the statement
tasks = session . execute ( task_stmt ). all ()El sistema de eventos utiliza un lenguaje de consulta ligeramente diferente.
from ftrack_query import FTrackQuery , event
from ftrack_query . event import attr , and_ , or_
with FTrackQuery () as session :
session . event_hub . subscribe ( str (
and_ (
attr ( 'topic' ) == 'ftrack.update' ,
attr ( 'data.user.name' ) != getuser (),
)
))
session . event_hub . wait () Tenga en cuenta que attr() , and_() y or_() están presentes en ftrack_query y ftrack_query.event . Estos no son intercambiables, por lo que si ambos son necesarios, entonces importe event y úselo como el espacio de nombres.
Sesión principal heredada de ftrack_api.Session .
Unir comparaciones múltiples.
Los atajos se proporcionan con & y | ( por ejemplo, attr(a).contains(b) & attr(x).contains(y) ).
Invierta las comparaciones de entrada.
Se proporciona un atajo con ~ ( p. Ej. ~attr(x).contains(y) ).
Utilizado para construir la cadena de consulta.
from ftrack_query import select
stmt = select ( entity ). where (...). populate (...) Llamar session.execute(stmt) ejecutará la consulta y devolverá el propio objeto QueryResult de FTrack, desde el cual se puede llamar .one() , .first() o .all() . Alternativamente, mediante el uso de la session.select(entity) , entonces esto se puede omitir.
Filtrar el resultado.
Usar palabras clave es la forma más rápida, como .where(first_name='Peter', last_name='Hunt') . Para cualquier cosa más compleja que las verificaciones de igualdad, se recomienda usar attr() , como .where(attr('project.metadata').any(attr('key') != 'disabled')) .
Atributos de entidad previa a la recolección.
Un ejemplo, para iterar a través del nombre de cada usuario, sería una buena idea llamar .populate('first_name', 'last_name') como parte de la consulta. Sin eso, tomaría 2 consultas separadas por usuario, que se conoce como el problema de consulta N+1.
Ordene los resultados por un atributo.
El atributo y el orden se pueden dar en el attr('name').desc() , o como una cadena sin procesar como name descending . El pedido de la orden se debe ascending si no se proporciona.
Invierta la dirección de clasificación.
Limite la cantidad de resultados a un cierto valor.
Nota: Esto es incompatible con llamar .first() o .one() .
En el caso de usar un límite, aplique un desplazamiento al resultado que se devuelve.
Solo para usuarios avanzados.
page_size : establezca el número de resultados que se obtendrán de inmediato desde ftrack.session : Adjunte un objeto de sesión a la consulta. Haga de la declaración una subconsulta para su uso dentro de .in_() .
Esto asegura que siempre hay una "selección de" como parte de la declaración. Establecer manualmente el parámetro de atributo anulará cualquier proyección existente.
Utilizado para crear nuevas entidades.
from ftrack_query import create
stmt = create ( entity ). values (...) Llamar session.execute(stmt) devolverá la entidad creada.
Valores para crear la entidad con.
Se utiliza para actualizar los valores de actualización en múltiples entidades. Esto se construye con el método select por lo que contiene muchos de los mismos métodos.
from ftrack_query import update
stmt = update ( entity ). where (...). values (...) Llamar session.execute(stmt) devolverá cuántas entidades se encontraron y actualizaron.
Filtrar qué actualizar.
Valores para actualizar la entidad.
Utilizado para eliminar entidades. Esto se construye con el método select por lo que contiene muchos de los mismos métodos.
from ftrack_query import delete
stmt = delete ( entity ). where (...). options ( remove_components = True ) Llamar session.execute(stmt) devolverá cuántas entidades se eliminaron.
Filtrar qué actualizar.
remove_components : elimine cualquier entidad Component de cada Location que lo contenga antes de eliminarlo. Esto no está habilitado de forma predeterminada, ya que no se puede retrasar. El objeto Comparison está diseñado para convertir los datos en una cadena. Contiene una amplia gama de operadores que se pueden usar con cualquier tipo de datos, incluidos otros objetos Comparison . El attr la función es un atajo para esto.
Cualquier comparación se puede revertir con el prefijo ~ o la función not_ .
attr(key) == 'value'attr(key) > 5attr(key).like('value%')attr(key).after(arrow.now().floor('day'))attr(key).has(subkey='value')attr(key).any(subkey='value')attr(key).in_(subquery)Comparaciones simples.
Realice una verificación para verificar si un atributo coincide con algún resultado.
Esto puede aceptar una subconsulta como .in_('select id from table where x is y') , o una lista de elementos como .in_(['x', 'y']) .
Compruebe si una cadena está contenida dentro de la consulta. Use un signo porcentual como like si se usa o not_like ; El resto son atajos y lo hacen automáticamente.
Prueba contra las relaciones escalar y recolección.
Prueba contra las fechas. Se recomienda usar objetos arrow .
# Project
select ( 'Project' )
# Project where status is active
select ( 'Project' ). where ( status = 'active' )
# Project where status is active and name like "%thrones"
select ( 'Project' ). where ( attr ( 'name' ). like ( '%thrones' ), status = 'active' )
# session.query('Project where status is active and (name like "%thrones" or full_name like "%thrones")')
select ( 'Project' ). where ( or_ ( attr ( 'name' ). like ( '%thrones' ), attr ( 'full_name' ). like ( '%thrones' )), status = 'active' )
# session.query('Task where project.id is "{0}"'.format(project['id']))
select ( 'Task' ). where ( project = project )
# session.query('Task where project.id is "{0}" and status.type.name is "Done"'.format(project['id']))
select ( 'Task' ). where ( attr ( 'status.type.name' ) == 'Done' , project = project )
# session.query('Task where timelogs.start >= "{0}"'.format(arrow.now().floor('day')))
select ( 'Task' ). where ( attr ( 'timelogs.start' ) >= arrow . now (). floor ( 'day' ))
# session.query('Note where author has (first_name is "Jane" and last_name is "Doe")')
select ( 'Note' ). where ( attr ( 'author' ). has ( first_name = 'Jane' , last_name = 'Doe' ))
# session.query('User where not timelogs any ()')
select ( 'User' ). where ( ~ attr ( 'timelogs' ). any ())
# projects = session.query('select full_name, status.name from Project')
select ( 'Project' ). populate ( 'full_name' , 'status.name' )
# select name from Project where allocations.resource[Group].memberships any (user.username is "john_doe")
select ( 'Project' ). select ( 'name' ). where ( attr ( 'allocations.resource[Group].memberships' ). any ( attr ( 'user.username' ) == 'john_doe' ))
# Note where parent_id is "{version_id}" or parent_id in (select id from ReviewSessionObject where version_id is "{version_id}")
select ( 'Note' ). where ( or_ ( attr ( 'parent_id' ). in_ ( select ( 'ReviewSessionObject' ). where ( version_id = version_id ). subquery ()), parent_id = version_id ))