Exemplos de uso SqlAlchemy
Lembrando que ja temos no blog um tutorial completo de uso do SqlAlchemy
A distribuição SQLAlchemy inclui uma variedade de exemplos de código que ilustram um conjunto selecionado de padrƵes, alguns tĆpicos e outros nĆ£o. Todos sĆ£o executĆ”veis āāe podem ser encontrados no
/examples
diretório da distribuição. Descrições e código fonte de todos podem ser encontrados aqui.
Exemplos adicionais de SQLAlchemy, com contribuição de alguns usuĆ”rios, estĆ£o disponĆveis no wiki em http://www.sqlalchemy.org/trac/wiki/UsageRecipes .
Mapeando Receitas
Lista de adjacĆŖncias
Um exemplo de uma estrutura de dicionÔrio de dicionÔrios mapeada usando um modelo de lista de adjacência.Ex .:
node = TreeNode('rootnode')
node.append('node1')
node.append('node3')
session.add(node)
session.commit()
dump_tree(node)
AssociaƧƵes
Exemplos que ilustram o uso do padrão "objeto de associação", em que uma classe intermediÔria medeia o relacionamento entre duas classes que estão associadas em um padrão de muitos para muitos.Listagem de arquivos:
proxied_association.py - O mesmo exemplo que basic_association, adicionando o uso desqlalchemy.ext.associationproxy
para fazer referĆŖncias explĆcitas aOrderItem
opcional.
basic_association.py - Ilustre um relacionamento muitos para muitos entre um "Pedido" e uma coleção de objetos "Item", associando um preço de compra a cada um deles por meio de um objeto de associação chamado "OrderItem"
dict_of_sets_with_default.py - Um exemplo avanƧado de proxy de associação que ilustra o aninhamento de proxies de associação para produzir coleƧƵes Python de vĆ”rios nĆveis, neste caso, um dicionĆ”rio com chaves de seqüência de caracteres e conjuntos de nĆŗmeros inteiros como valores, que ocultam as classes mapeadas subjacentes.
GrƔficos direcionados
Um exemplo de persistência para uma estrutura de grÔfico direcionado. O grÔfico é armazenado como uma coleção de arestas, cada uma referenciando um nó "inferior" e um "superior" em uma tabela de nós. A persistência bÔsica e a consulta de vizinhos inferiores e superiores são ilustradas:n2 = Node(2)
n5 = Node(5)
n2.add_neighbor(n5)
print n2.higher_neighbors()
Relações dinâmicas como dicionÔrios
Ilustra como colocar uma fachada semelhante a um dicionÔrio em cima de uma relação "dinâmica", para que as operações do dicionÔrio (assumindo simples teclas de seqüência de caracteres) possam operar em uma grande coleção sem carregar a coleção completa de uma só vez.Listagem de arquivos:
AssociaƧƵes genƩricas
Ilustra vĆ”rios mĆ©todos de associação de vĆ”rios tipos de pais a um objeto filho especĆfico.Todos os exemplos usam a extensĆ£o declarativa junto com mixins declarativos. Cada uma apresenta o caso de uso idĆŖntico no final - duas classes
Customer
e Supplier
, ambas subclassificando o HasAddresses
mixin, o que garante que a classe pai seja fornecida com uma addresses
coleção que contenha Address
objetos.Os scripts discriminator_on_association.py e generic_fk.py são versões modernizadas de receitas apresentadas na postagem de blog de 2007 Polymorphic Associations with SQLAlchemy .
Listagem de arquivos:
table_per_association.py - ilustra um mixin que fornece uma associação genérica por meio de tabelas de associação geradas individualmente para cada classe pai. Os próprios objetos associados são mantidos em uma única tabela compartilhada entre todos os pais.
table_per_related.py - ilustra uma associação genĆ©rica que persiste objetos de associação em tabelas individuais, cada uma gerada para persistir esses objetos em nome de uma classe pai especĆfica.
discriminator_on_association.py - Ilustra um mixin que fornece uma associação genĆ©rica usando uma Ćŗnica tabela de destino e uma Ćŗnica tabela de associação, referida por todas as tabelas pai. A tabela de associação contĆ©m uma coluna "discriminador" que determina que tipo de objeto pai se associa a cada linha especĆfica na tabela de associação.
generic_fk.py - Ilustra a chamada āchave estrangeira genĆ©ricaā, de maneira semelhante Ć de estruturas populares como Django, ROR etc. Essa abordagem ignora as prĆ”ticas de integridade referencial padrĆ£o, pois a coluna āchave estrangeiraā nĆ£o Ć© realmente restrito a se referir a qualquer tabela especĆfica; em vez disso, a lógica no aplicativo Ć© usada para determinar qual tabela Ć© referenciada.
ColeƧƵes grandes
Exemplo de coleção grande.Ilustra as opções a serem usadas
relationship()
quando a lista de objetos relacionados Ć© muito grande, incluindo:- Relacionamentos ādinĆ¢micosā que consultam fatias de dados acessadas
- como usar o ON DELETE CASCADE em conjunto com
passive_deletes=True
para melhorar significativamente o desempenho da exclusão de coleção relacionada.
Caminhos materializados
Ilustra o padrão de "caminhos materializados" para dados hierÔrquicos usando o SQLAlchemy ORM.Listagem de arquivos:
materialized_paths.py - Ilustra o padrão de "caminhos materializados".
Conjuntos aninhados
Ilustra uma maneira rudimentar de implementar o padrão de "conjuntos aninhados" para dados hierÔrquicos usando o SQLAlchemy ORM.Listagem de arquivos:
nested_sets.py - Estrutura em Ɣrvore dos "conjuntos aninhados" da Celko.
Desempenho
Um conjunto de perfis de desempenho para uma variedade de casos de uso SQLAlchemy.Cada conjunto se concentra em um caso de uso especĆfico com um perfil de desempenho especĆfico e implicaƧƵes associadas:
- inserƧƵes em massa
- inserƧƵes individuais, com ou sem transaƧƵes
- buscando um grande nĆŗmero de linhas
- executando muitas consultas curtas
Uma ferramenta de linha de comando Ć© apresentada no nĆvel do pacote que permite que conjuntos individuais sejam executados:
$ python -m examples.performance --help
usage: python -m examples.performance [-h] [--test TEST] [--dburl DBURL]
[--num NUM] [--profile] [--dump]
[--runsnake] [--echo]
{bulk_inserts,large_resultsets,single_inserts}
positional arguments:
{bulk_inserts,large_resultsets,single_inserts}
suite to run
optional arguments:
-h, --help show this help message and exit
--test TEST run specific test name
--dburl DBURL database URL, default sqlite:///profile.db
--num NUM Number of iterations/items/etc for tests;
default is module-specific
--profile run profiling and dump call counts
--dump dump full call profile (implies --profile)
--runsnake invoke runsnakerun (implies --profile)
--echo Echo SQL output
$ python -m examples.performance bulk_inserts
$ python -m examples.performance bulk_inserts \
--dburl mysql+mysqldb://scott:tiger@localhost/test \
--profile --num 1000
Listagem de arquivos
Listagem de arquivos:
bulk_updates.py - Essa série de testes ilustra maneiras diferentes de atualizar um grande número de linhas em massa.
large_resultsets.py - Nesta série de testes, estamos aguardando o momento para carregar um grande número de linhas muito pequenas e simples.
bulk_inserts.py - Esta série de testes ilustra maneiras diferentes de INSERIR um grande número de linhas em massa.
short_selects.py - Esta série de testes ilustra maneiras diferentes de selecionar um único registro pela chave primÔria
single_inserts.py - Nesta série de testes, estamos analisando um método que insere uma linha em uma transação distinta e, posteriormente, retorna ao estado essencialmente "fechado". Isso seria anÔlogo a uma chamada de API que inicia uma conexão com o banco de dados, insere a linha, confirma e fecha.
__main__.py - Permite que o pacote de exemplos / desempenho seja executado como um script.
Executando todos os testes com o tempo
Esta é a forma padrão de execução:$ python -m examples.performance single_inserts
Tests to run: test_orm_commit, test_bulk_save,
test_bulk_insert_dictionaries, test_core,
test_core_query_caching, test_dbapi_raw_w_connect,
test_dbapi_raw_w_pool
test_orm_commit : Individual INSERT/COMMIT pairs via the
ORM (10000 iterations); total time 13.690218 sec
test_bulk_save : Individual INSERT/COMMIT pairs using
the "bulk" API (10000 iterations); total time 11.290371 sec
test_bulk_insert_dictionaries : Individual INSERT/COMMIT pairs using
the "bulk" API with dictionaries (10000 iterations);
total time 10.814626 sec
test_core : Individual INSERT/COMMIT pairs using Core.
(10000 iterations); total time 9.665620 sec
test_core_query_caching : Individual INSERT/COMMIT pairs using Core
with query caching (10000 iterations); total time 9.209010 sec
test_dbapi_raw_w_connect : Individual INSERT/COMMIT pairs w/ DBAPI +
connection each time (10000 iterations); total time 9.551103 sec
test_dbapi_raw_w_pool : Individual INSERT/COMMIT pairs w/ DBAPI +
connection pool (10000 iterations); total time 8.001813 sec
Despejando perfis para testes individuais
Uma saĆda de perfil Python pode ser descarregada para todos os testes ou, geralmente, para testes individuais:$ python -m examples.performance single_inserts --test test_core --num 1000 --dump
Tests to run: test_core
test_core : Individual INSERT/COMMIT pairs using Core. (1000 iterations); total fn calls 186109
186109 function calls (186102 primitive calls) in 1.089 seconds
Ordered by: internal time, call count
ncalls tottime percall cumtime percall filename:lineno(function)
1000 0.634 0.001 0.634 0.001 {method 'commit' of 'sqlite3.Connection' objects}
1000 0.154 0.000 0.154 0.000 {method 'execute' of 'sqlite3.Cursor' objects}
1000 0.021 0.000 0.074 0.000 /Users/classic/dev/sqlalchemy/lib/sqlalchemy/sql/compiler.py:1950(_get_colparams)
1000 0.015 0.000 0.034 0.000 /Users/classic/dev/sqlalchemy/lib/sqlalchemy/engine/default.py:503(_init_compiled)
1 0.012 0.012 1.091 1.091 examples/performance/single_inserts.py:79(test_core)
...
Usando RunSnake
Esta opção requer que a ferramenta de linha de comando RunSnake esteja instalada:$ python -m examples.performance single_inserts --test test_core --num 1000 --runsnake
Escrevendo suas próprias suĆtes
O sistema do conjunto de profiler Ć© extensĆvel e pode ser aplicado ao seu próprio conjunto de testes. Essa Ć© uma tĆ©cnica valiosa a ser usada na decisĆ£o da abordagem adequada para algum conjunto de rotinas crĆticas ao desempenho. Por exemplo, se quisermos criar um perfil da diferenƧa entre vĆ”rios tipos de carregamento, podemos criar um arquivotest_loads.py
com o seguinte conteĆŗdo:from examples.performance import Profiler
from sqlalchemy import Integer, Column, create_engine, ForeignKey
from sqlalchemy.orm import relationship, joinedload, subqueryload, Session
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = None
session = None
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship("Child")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
# Init with name of file, default number of items
Profiler.init("test_loads", 1000)
@Profiler.setup_once
def setup_once(dburl, echo, num):
"setup once. create an engine, insert fixture data"
global engine
engine = create_engine(dburl, echo=echo)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
sess = Session(engine)
sess.add_all([
Parent(children=[Child() for j in range(100)])
for i in range(num)
])
sess.commit()
@Profiler.setup
def setup(dburl, echo, num):
"setup per test. create a new Session."
global session
session = Session(engine)
# pre-connect so this part isn't profiled (if we choose)
session.connection()
@Profiler.profile
def test_lazyload(n):
"load everything, no eager loading."
for parent in session.query(Parent):
parent.children
@Profiler.profile
def test_joinedload(n):
"load everything, joined eager loading."
for parent in session.query(Parent).options(joinedload("children")):
parent.children
@Profiler.profile
def test_subqueryload(n):
"load everything, subquery eager loading."
for parent in session.query(Parent).options(subqueryload("children")):
parent.children
if __name__ == '__main__':
Profiler.main()
$ python test_loads.py --dburl postgresql+psycopg2://scott:tiger@localhost/test
Running setup once...
Tests to run: test_lazyload, test_joinedload, test_subqueryload
test_lazyload : load everything, no eager loading. (1000 iterations); total time 11.971159 sec
test_joinedload : load everything, joined eager loading. (1000 iterations); total time 2.754592 sec
test_subqueryload : load everything, subquery eager loading. (1000 iterations); total time 2.977696 sec
$ python test_loads.py --num 100 --runsnake --test test_joinedload
Condições de junção de relacionamento
Exemplos de vƔriasorm.relationship()
configuraƧƵes, que fazem uso do primaryjoin
argumento para compor tipos especiais de condições de junção.Listagem de arquivos:
threeway.py - Ilustre uma ājunção de trĆŖs viasā - onde uma tabela principal se une a uma tabela remota por meio de uma tabela de associação, mas a tabela principal tambĆ©m precisa se referir a algumas colunas diretamente na tabela remota.
cast.py - Ilustre umrelationship()
que une duas colunas em que essas colunas não são do mesmo tipo e um CAST deve ser usado no lado do SQL para correspondê-las.
Space Invaders
Um jogo Space Invaders usando SQLite como mƔquina de estado.Originalmente desenvolvido em 2012. Adaptado para trabalhar em Python 3.
Ć executado em um console de texto usando arte ASCII.

python -m examples.space_invaders.space_invaders
tail -f space_invaders.log
Listagem de arquivos:
XML PersistĆŖncia
Ilustra trĆŖs estratĆ©gias para persistir e consultar documentos XML, conforme representado pelo ElementTree em um banco de dados relacional. As tĆ©cnicas nĆ£o aplicam nenhum mapeamento aos objetos ElementTree diretamente, portanto, sĆ£o compatĆveis com o cElementTree nativo e com o lxml e podem ser adaptados para se adequar a qualquer tipo de sistema de representação DOM. A consulta ao longo de seqüências semelhantes a xpath tambĆ©m Ć© ilustrada.Ex .:
# parse an XML file and persist in the database
doc = ElementTree.parse("test.xml")
session.add(Document(file, doc))
session.commit()
# locate documents with a certain path/attribute structure
for document in find_document('/somefile/header/field2[@attr=foo]'):
# dump the XML
print document
pickle_type.py - ilustra uma maneira rƔpida e suja de manter um documento XML expresso usando ElementTree e pickle.
adjacency_list.py - ilustra uma maneira explĆcita de manter um documento XML expresso usando o ElementTree.
optimized_al.py - Usa a mesma estratƩgia deadjacency_list.py
, mas associa cada linha do DOM à sua própria linha de documento, para que um documento completo dos nós do DOM possa ser carregado usando consultas O (1) - a construção da "hierarquia" é executada após o carregar de forma não recursiva e é mais eficiente.
Versionamento Objects
Controle de versão com uma tabela de histórico
Ilustra uma extensão que cria tabelas de versões para entidades e armazena registros para cada alteração. As extensões fornecidas geram uma classe "history" anÓnima que representa versões históricas do objeto de destino.Compare com os exemplos de controle de versão usando Linhas Temporais que gravam atualizações como novas linhas na mesma tabela, sem usar uma tabela de histórico separada.
O uso é ilustrado através de um módulo de teste de unidade
test_versioning.py
, que pode ser executado atravƩs de py.test
:# assume SQLAlchemy is installed where py.test is
cd examples/versioned_history
py.test test_versioning.py
from history_meta import Versioned, versioned_session
Base = declarative_base()
class SomeClass(Versioned, Base):
__tablename__ = 'sometable'
id = Column(Integer, primary_key=True)
name = Column(String(50))
def __eq__(self, other):
assert type(other) is SomeClass and other.id == self.id
Session = sessionmaker(bind=engine)
versioned_session(Session)
sess = Session()
sc = SomeClass(name='sc1')
sess.add(sc)
sess.commit()
sc.name = 'sc1modified'
sess.commit()
assert sc.version == 2
SomeClassHistory = SomeClass.__history_mapper__.class_
assert sess.query(SomeClassHistory).\
filter(SomeClassHistory.version == 1).\
all() \
== [SomeClassHistory(version=1, name='sc1')]
Versioned
mixin é projetado para funcionar com declarativo. Para usar a extensão com mapeadores clÔssicos, a _history_mapper
função pode ser aplicada:from history_meta import _history_mapper
m = mapper(SomeClass, sometable)
_history_mapper(m)
SomeHistoryClass = SomeClass.__history_mapper__.class_
test_versioning.py - Testes de unidade que ilustram o uso dashistory_meta.py
funções do módulo.
history_meta.py - Classe de mixagem com versão e outros utilitÔrios.
Controle de versão usando linhas temporais
VÔrios exemplos que ilustram a técnica de interceptar alterações que seriam primeiro interpretadas como um UPDATE em uma linha e, em vez disso, transformÔ-lo em um INSERT de uma nova linha, deixando a linha anterior intacta como uma versão histórica.Compare com o exemplo Controle de versão com uma tabela de históricoque grava uma linha do histórico em uma tabela de histórico separada.
Listagem de arquivos:
versioned_rows.py - ilustra um método para interceptar alterações em objetos, transformando uma instrução UPDATE em uma única linha em uma instrução INSERT, para que uma nova linha seja inserida com os novos dados, mantendo a linha antiga intacta.
versioned_rows_w_versionid.py - ilustra um método para interceptar alterações em objetos, transformando uma instrução UPDATE em uma única linha em uma instrução INSERT, para que uma nova linha seja inserida com os novos dados, mantendo a linha antiga intacta.
versioned_map.py - Uma variante do exemplo versioned_rows criada em torno do conceito de uma estrutura de "tabela vertical", como as ilustradas nos exemplos do Vertical Attribute Mapping .
versioned_update_old_row.py - Ilustra a mesma tƩcnica UPDATE into INSERT deversioned_rows.py
, mas também emite uma UPDATE na linha antiga para afetar uma alteração no carimbo de data / hora. Também inclui umQueryEvents.before_compile()
gancho para limitar as consultas apenas à versão mais recente.
Mapeamento Vertical de Atributos
Ilustra os mapeamentos da ātabela verticalā.Uma ātabela verticalā refere-se a uma tĆ©cnica em que atributos individuais de um objeto sĆ£o armazenados como linhas distintas em uma tabela. A tĆ©cnica ātabela verticalā Ć© usada para persistir objetos que podem ter um conjunto variado de atributos, Ć s custas do controle e da concisĆ£o simples da consulta. Ć comumente encontrado em sistemas de gerenciamento de conteĆŗdo / documento para representar estruturas criadas pelo usuĆ”rio de maneira flexĆvel.
Duas variantes na abordagem são dadas. Na segunda, cada linha faz referência a um "tipo de dados" que contém informações sobre o tipo de informação armazenada no atributo, como número inteiro, sequência ou data.
Exemplo:
shrew = Animal(u'shrew')
shrew[u'cuteness'] = 5
shrew[u'weasel-like'] = False
shrew[u'poisonous'] = True
session.add(shrew)
session.flush()
q = (session.query(Animal).
filter(Animal.facts.any(
and_(AnimalFact.key == u'weasel-like',
AnimalFact.value == True))))
print 'weasel-like animals', q.all()
dictlike-polymorphic.py - Mapeando uma tabela vertical com valor polimórfico como um dicionÔrio.
dictlike.py - Mapeando uma tabela vertical como um dicionƔrio.
Receitas de mapeamento de heranƧa
Mapeamentos bƔsicos de heranƧa
Exemplos de trabalho de herança de tabela única, tabela unida e tabela de concreto, conforme descrito em Hierarquias de herança de classe de mapeamento .Listagem de arquivos:
join.py - Exemplo de heranƧa de tabela unida (tabela por subclasse).
concrete.py - Betão-tabela (tabela-per-classe) exemplo herança.
single.py - Exemplo de herança de tabela única (tabela por hierarquia).
APIs especiais
Instrumentação de Atributos
Exemplos que ilustram modificaƧƵes no sistema de gerenciamento de atributos do SQLAlchemy.Listagem de arquivos:
listen_for_events.py - ilustra como anexar eventos a todos os atributos instrumentados e ouvir eventos de alteração.
active_column_defaults.py - ilustra o uso doAttributeEvents.init_scalar()
evento, em conjunto com os padrões da coluna Core, para fornecer objetos ORM que produzem automaticamente o valor padrão quando um atributo não definido é acessado.
custom_management.py - ilustra a instrumentação de classe personalizada, usando osqlalchemy.ext.instrumentation
pacote de extensão.
Sharding Horizontal
Um exemplo bÔsico de uso da API SQLAlchemy Sharding. O sharding refere-se à escala horizontal de dados em vÔrios bancos de dados.Os componentes bÔsicos de um mapeamento "fragmentado" são:
- vƔrios bancos de dados, cada um com um 'shard id'
- uma função que pode retornar um único ID de fragmento, dada uma instância a ser salva; isso é chamado de "shard_chooser"
- uma função que pode retornar uma lista de IDs de shard que se aplicam a um identificador de instĆ¢ncia especĆfico; isso Ć© chamado de "id_chooser". Se retornar todos os IDs de shard, todos os shards serĆ£o pesquisados.
- uma função que pode retornar uma lista de IDs de shard para tentar, dada uma consulta especĆfica ("query_chooser"). Se retornar todos os IDs de shard, todos os shards serĆ£o consultados e os resultados serĆ£o reunidos.
A construção de rotinas genĆ©ricas de fragmentação Ć© uma abordagem ambiciosa para a questĆ£o da organização de instĆ¢ncias entre vĆ”rios bancos de dados. Para uma alternativa mais clara, a abordagem "entidade distinta" Ć© um mĆ©todo simples de atribuir objetos a diferentes tabelas (e potencialmente nós do banco de dados) de maneira explĆcita - descrita no wiki em EntityName .
Listagem de arquivos:
Estendendo o ORM
Cache de Dogpile
Ilustra como incorporar a funcionalidade dogpile.cache aoQuery
objeto, permitindo o controle total do cache, bem como a capacidade de extrair atributos de "carregamento lento" do cache de longo prazo.Nesta demonstração, as seguintes técnicas são ilustradas:
- Usando subclasses personalizadas de
Query
- TƩcnica bƔsica de contornar a consulta para extrair de uma fonte de cache personalizada em vez do banco de dados.
- Cache rudimentar com dogpile.cache, usando "regiƵes" que permitem controle global sobre um conjunto fixo de configuraƧƵes.
- Usando
MapperOption
objetos personalizados para configurar opƧƵes em uma Consulta, incluindo a capacidade de chamar as opƧƵes em profundidade em um grƔfico de objeto quando ocorrem cargas preguiƧosas.
# query for Person objects, specifying cache
q = Session.query(Person).options(FromCache("default"))
# specify that each Person's "addresses" collection comes from
# cache too
q = q.options(RelationshipCache(Person.addresses, "default"))
# query
print q.all()
Os próprios scripts de demonstração, em ordem de complexidade, são executados como módulos Python, para que as importações relativas funcionem:
python -m examples.dogpile_caching.helloworld
python -m examples.dogpile_caching.relationship_caching
python -m examples.dogpile_caching.advanced
python -m examples.dogpile_caching.local_session_caching
environment.py - Estabeleça caminhos e configurações de arquivo de dados / cache, dados do dispositivo de inicialização, se necessÔrio.
caching_query.py - Representa funções e classes que permitem o uso do armazenamento em cache Dogpile com SQLAlchemy. Apresenta uma opção de consulta chamada FromCache.
model.py - O modelo de dados, que representa a Pessoa que possui vĆ”rios objetos de EndereƧo, cada um com Código Postal, Cidade, PaĆs.
fixture_data.py - Instala alguns dados de amostra. Aqui temos alguns códigos postais para algumas cidades dos EUA / CanadÔ. Em seguida, 100 registros de Pessoa são instalados, cada um com um código postal selecionado aleatoriamente.
helloworld.py - Ilustre como carregar alguns dados e armazenar em cache os resultados.
relationship_caching.py - Ilustra como adicionar opƧƵes de cache nos pontos de extremidade do relacionamento, para que o lazyload seja carregado do cache.
advanced.py - Ilustra o uso de Query combinado com a opção FromCache, incluindo carregamento de front-end, invalidação de cache e armazenamento em cache de coleção.
local_session_caching.py - Este exemplo cria um novo backend dogpile.cache que manterÔ os dados em um dicionÔrio local da sessão atual. remove () a sessão e o cache se foi.
Integração PostGIS
Um exemplo ingênuo que ilustra técnicas para ajudar a incorporar a funcionalidade PostGIS.Este exemplo foi desenvolvido originalmente na esperança de que fosse extrapolado para uma camada abrangente de integração do PostGIS. Temos o prazer de anunciar que isso se concretizou como GeoAlquimia .
O exemplo ilustra:
- uma extensão DDL que permite que CREATE / DROP funcione em conjunto com AddGeometryColumn / DropGeometryColumn
- um tipo de geometria, além de alguns subtipos, que convertem os valores da linha de resultado em um objeto que reconhece GIS e também se integra à extensão DDL.
- um objeto que reconhece GIS que armazena um valor de geometria bruta e fornece uma fƔbrica para funƧƵes como AsText ().
- um comparador ORM que pode substituir métodos de coluna padrão em objetos mapeados para produzir operadores GIS.
- um ouvinte de evento de atributo que intercepta cadeias e converte em GeomFromText ().
- um exemplo de operador independente.
Ex .:
print session.query(Road).filter(
Road.road_geom.intersects(r1.road_geom)).all()
0 ComentƔrios