2010-05-10 4 views
2

En raison des données existantes qui ne sont pas disponibles dans la base de données, mais certains fichiers externes, je veux créer un objet SQLAlchemy qui contient des données lues à partir des fichiers externes, mais ne sont pas écrites dans la base de données si j'exécute session.flush()Comment créer un objet Elixir/SQLAlchemy non persistant?

mon code ressemble à ceci:

try: 
    return session.query(Phone).populate_existing().filter(Phone.mac == ident).one() 
except: 
    return self.createMockPhoneFromLicenseFile(ident) 

def createMockPhoneFromLicenseFile(self, ident): 
    # Some code to read necessary data from file deleted.... 
    phone = Phone() 
    phone.mac = foo 
    phone.data = bar 
    phone.state = "Read from legacy file" 
    phone.purchaseOrderPosition = self.getLegacyOrder(ident) 
    # SQLAlchemy magic doesn't seem to work here, probably because we don't insert the created 
    # phone object into the database. So we set the id fields manually. 
    phone.order_id = phone.purchaseOrderPosition.order_id 
    phone.order_position_id = phone.purchaseOrderPosition.order_position_id 
    return phone 

Tout fonctionne bien, sauf que sur un session.flush() exécuté plus tard dans l'application SQLAlchemy tente d'écrire l'objet créé de téléphone à la base de données (qui ne réussit pas, heureusement, parce que phone.state est plus long que le type de données le permet), ce qui casse la fonction qui génère le flush.

Existe-t-il un moyen d'empêcher SQLAlchemy d'essayer d'écrire un tel objet?

Mise à jour

Bien que je ne trouve rien sur

using_mapper_options(save_on_init=False) 

dans la documentation Elixir (vous pouvez peut-être fournir un lien?), Il m'a semblé la peine d'essayer (je ont préféré un moyen d'empêcher qu'une seule instance soit écrite à la place de l'entité entière). Au début, il semblait que l'instruction n'avait aucun effet et je soupçonnais que mes versions de SQLAlchemy/Elixir étaient trop anciennes, mais j'ai découvert que la connexion à l'entité PurchaseOrderPosition (que je n'ai pas modifiée) faite avec

phone.purchaseOrderPosition = self.getLegacyOrder(ident) 

provoque l'écriture de l'objet téléphone à nouveau. Si je supprime la déclaration, tout semble aller bien.

+0

J'ai mis à jour ma réponse. –

Répondre

3

Vous devez faire

import elixir 
elixir.options_defaults['mapper_options'] = { 'save_on_init': False } 

pour éviter Entity cas que vous instancier être automatiquement ajoutés à la session. Idéalement, cela devrait être fait le plus tôt possible dans votre code. Vous pouvez également le faire pour chaque entité, via using_mapper_options(save_on_init=False) - voir la documentation Elixir pour plus de détails.

Mise à jour:

Voir this post sur la liste de diffusion Elixir indiquant que c'est la solution. En outre, comme le souligne Ants Aasma, vous pouvez utiliser des options en cascade sur la relation Elixir pour configurer les options de cascade dans SQLAlchemy. Voir this page pour plus de détails.après Old

+0

S'il vous plaît voir la section de mise à jour dans ma question pour mes commentaires à votre réponse. – siebert

+0

En plus d'éviter d'impliquer Session.add sur la création d'objets, vous devrez également éviter les cascades sur les relations. Voir la documentation en cascade dans les documents SQLAlchemy si Elixir ne le documente pas, Elixir devrait toujours permettre de le définir. –

0

Eh bien, sqlalchemy ne fonctionne pas, par défaut.

Considérons l'exemple de code autonome suivant. Donc, je ne suis pas sûr de l'implicite d'ajouter vos instances à la session. Normalement, vous devez appeler manuellement s.add(u) pour le faire passer à la session. Je ne suis pas familier avec elixir alors peut-être que c'est une supercherie d'élixir ... Peut-être que vous pourriez le retirer de la session, en utilisant session.expunge().

Questions connexes