Eu enfrentei um problema [1] ao ter um modelo com um TextField e um
campo foreignkey ou manytomanyfield armazenados em um BD Oracle.
O problema ocorre quando eu tento realizar uma busca e o campo com
chave estrangeira está incluído na busca (incluído na variável
search_field no admin.py). Aparece a mensagem de erro "*DatabaseError:
ORA-00932: inconsistent datatypes: expected - got CLOB*". Isso pq,
quando tem uma chave estrangeira na busca, o django insere um DISTINCT
no select do sql gerado [2], só que o oracle não suporta SELECT
DISTINCT em campos CLOB (que é como um TextField é armazenado).
Bom, pra contornar isso, a melhor maneira que eu achei foi criar um
field TextField personalizado que, em vez de armazenar os dados em uma
coluna CLOB, armazena em um VARCHAR2. O problema que estou enfrentando
é que não estou conseguindo mostrar uma mensagem de erro quando alguém
insere mais que 4000 chars (capacidade máxima de um VARCHAR2) e salva
o objeto. O objeto acaba sendo salvo sem mostrar msg de erro.
Vejam como está o código: http://dpaste.com/hold/16484/
Onde estou errando? Mesmo que eu tire o if do método clean(), deixando
levantar a exceção independente do que foi inserido, a msg não
aparece...
Outra maneira para contornar esse problema seria só realizar um SELECT
DISTINCT em campos estrangeiros, e não em campos "locais". Ou seja, em
[2], ao invés de fazer "qs = qs.distinct()" e afetar todos os SELECTs
gerados (incluindo aqui os TextFields), afetar somente os SELECTs
feitos em outras tabelas, ficando de fora os campos CLOB. Mas eu não
olhei como é a estrutura desse objeto "qs" pra saber se é possível
definir internamente em que campo será feito DISTINCT e em que campo
não será. Creio que essa seja a melhor solução, pois evitaria soluções
técnicas para contorno de adversidades (vulgo "gambiarra").
Valeu!!
[1] http://groups.google.com/group/django-users/browse_thread/thread/cd6b14ede0980131
[2] http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/views/main.py?rev=7967#L225
--
João Olavo Baião de Vasconcelos
Bacharel em Ciência da Computação
Analista de Sistemas - Infraestrutura
joaoolavo.wordpress.com
já pensou em fazer uma VIEW no oracle e depois acessar ela?
Oi João,
Sobre o fato de "como o django irá usar essa view" eu precisei fazer
isso esta semana, mas com o postgresql.
Basicamente o django não vai fazer diferença se é uma tabela ou uma
view. Ele simplesmente vai executar, por exemplo, um "SELECT * FROM
cliente_cliente" e aí o problema é do banco de dados de como irá
retornar os dados.
No caso eu criei uma view com a mesma estrutura da tabela "real" (que na
verdade tem outro nome).
No models.py você teria que colocar a opção managed = False na classe
Meta (para o django não criar a tabela no syncdb).
Até aí você teria metade o problema resolvido... o django iria consultar
a sua view como se fosse uma tabela real.
A outra metade do problema é que não tem como você dar um
insert/update/delete na view (pelo menos no postgresql não... também não
sei como seria o caso numa view materializada). Mas enfim.... eu tive
que criar uma RULES (que é praticamente um primo da trigger) para que
caso ocorra insert/update/delete ele não faz nada na view e executa
essas operacoes na tabela "real".
Bom... caso você venha precisa usar view's o caminho das pedras será
mais ou menos este =)
Abraços,
Sérgio Durand
Basicamente o django não vai fazer diferença se é uma tabela ou uma view. Ele simplesmente vai executar, por exemplo, um "SELECT * FROM cliente_cliente" e aí o problema é do banco de dados de como irá retornar os dados.