O Ftrack Query é um invólucro orientado a objetos sobre a API FTRACK. Embora a sintaxe de consulta padrão seja poderosa, ela é totalmente baseada em texto para que consultas dinâmicas possam ser difíceis de construir. Este módulo suporta e / ou operadores com comparações aninhadas.
Recomenda-se ler primeiro https://ftrack-python-api.readthedocs.io/en/stable/tutorial.html para obter uma compreensão básica de como a API do FTRACK funciona.
pip install ftrack_query
Em vez de escrever toda a sequência de consultas de uma só vez, uma "instrução" é construída ( por exemplo, stmt = select('Task') ), e a consulta pode ser construída chamando métodos como .where() e .populate() na instrução.
Todos os métodos CRUD são suportados ( create , select , update , delete ), mas a funcionalidade principal foi projetada para uso com select . As declarações são construídas com uma sintaxe semelhante à API principal, para que seja simples a transição entre os dois.
Observe que isso é totalmente compatível com versões anteriores; portanto, as consultas existentes não precisam ser reescritas.
O exemplo abaixo é para consultas muito 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 um exemplo muito mais complexo:
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 ()O sistema de eventos usa uma linguagem de consulta ligeiramente 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 () Observe que attr() and_() e or_() estão presentes em ftrack_query e ftrack_query.event . Eles não são intercambiáveis; portanto, se forem necessários, importe event e use -o como espaço para nome.
Sessão principal herdada de ftrack_api.Session .
Junte -se a várias comparações.
Os atalhos são fornecidos com & e | ( por exemplo, attr(a).contains(b) & attr(x).contains(y) ).
Reverta as comparações de entrada.
Um atalho é fornecido com ~ ( por exemplo, ~attr(x).contains(y) ).
Usado para construir a corda de consulta.
from ftrack_query import select
stmt = select ( entity ). where (...). populate (...) Chamall session.execute(stmt) executará a consulta e retornará o objeto QueryResult do próprio Ftrack, do qual .one() , .first() ou .all() pode ser chamado. Como alternativa, usando o atalho session.select(entity) , isso pode ser ignorado.
Filtre o resultado.
O uso de palavras -chave é a maneira mais rápida, como .where(first_name='Peter', last_name='Hunt') . Para qualquer coisa mais complexa do que as verificações de igualdade, o uso de attr() é recomendado, como .where(attr('project.metadata').any(attr('key') != 'disabled')) .
Atributos da entidade pré-busca.
Um exemplo, para iterar através do nome de todo usuário, seria uma boa ideia chamar .populate('first_name', 'last_name') como parte da consulta. Sem isso, foram necessárias 2 consultas separadas por usuário, conhecido como problema de consulta N+1.
Classifique os resultados por um atributo.
O atributo e a ordem podem ser fornecidos no formato attr('name').desc() , ou como uma corda crua como o name descending . O pedido será padrão para ascending se não for fornecido.
Reverta a direção de classificação.
Limite a quantidade de resultados a um determinado valor.
Nota: Isso é incompatível com chamadas .first() ou .one() .
No caso de usar um limite, aplique um deslocamento ao resultado que é retornado.
Apenas para usuários avançados.
page_size : Defina o número de resultados a serem buscados imediatamente no Ftrack.session : Anexe um objeto de sessão à consulta. Torne a declaração uma subconsulta para uso dentro .in_() .
Isso garante que sempre haja uma "seleção de" como parte da declaração. A configuração manualmente do parâmetro do atributo substituirá quaisquer projeções existentes.
Usado para criar novas entidades.
from ftrack_query import create
stmt = create ( entity ). values (...) Calling session.execute(stmt) retornará a entidade criada.
Valores para criar a entidade com.
Usado para atualizar valores de atualização em várias entidades. Isso é criado fora do método select , portanto, contém muitos dos mesmos métodos.
from ftrack_query import update
stmt = update ( entity ). where (...). values (...) Chamalizar session.execute(stmt) retornará quantas entidades foram encontradas e atualizadas.
Filtre o que atualizar.
Valores a serem atualizados na entidade.
Usado para excluir entidades. Isso é criado fora do método select , portanto, contém muitos dos mesmos métodos.
from ftrack_query import delete
stmt = delete ( entity ). where (...). options ( remove_components = True ) Chamalizar session.execute(stmt) retornará quantas entidades foram excluídas.
Filtre o que atualizar.
remove_components : Remova qualquer entidade Component de todos Location que a contêm antes de ser excluída. Isso não está ativado por padrão, pois não pode ser revertido. O objeto Comparison foi projetado para converter dados em uma string. Ele contém uma ampla gama de operadores que podem ser usados contra qualquer tipo de dados, incluindo outros objetos Comparison . O attr de função é um atalho para isso.
Qualquer comparação pode ser revertida com o prefixo ~ ou a função 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)Comparações simples.
Execute uma verificação para verificar se um atributo corresponde a quaisquer resultados.
Isso .in_(['x', 'y']) aceitar uma subconsulta .in_('select id from table where x is y')
Verifique se uma string está contida na consulta. Use um sinal percentual como curinga se estiver like ou not_like ; O restante são atalhos e fazem isso automaticamente.
Teste contra relacionamentos escalares e de coleta.
Teste contra datas. O uso de objetos arrow é recomendado.
# 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 ))