2011-04-14 3 views
3

J'ai une structure de données simple, où une table de film a une clé étrangère à la table de pays.sqlalchemy relation auto-référentielle n'incluant pas 'self'

Pour récupérer tous les films d'un même pays, j'ai cette propriété 'same_country_films', une relation auto-référentielle.

Il fait presque le travail correctement, mais il inclut également le film lui-même dans la liste. Comment puis-je exclure il et juste avoir autres films?

Merci beaucoup!

from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey 
from sqlalchemy.orm import mapper, relationship 
metadata = MetaData() 
country_table = Table('country', metadata, 
    Column('id', String, primary_key=True), 
    Column('name', String), 
    ) 
film_table = Table('film', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('title', String), 
    Column('year', Integer), 
    Column('country_id', Integer, ForeignKey('country.id')) 
    ) 

class Country(object): 
    pass 

class Film(object): 
    pass 

mapper(Country, country_table) 

mapper(Film, film_table, 
     properties={ 
      'country':relationship(
        Country, 
        backref='films'), 
      'same_country_films':relationship(
        Film, 
        primaryjoin=film_table.c.country_id==\ 
           film_table.c.country_id, 
        foreign_keys=[ 
         film_table.c.country_id, 
         ] 
        ) 
      } 
    ) 

Répondre

0

Cela devrait le faire, je pense, (bien que je ne l'ai pas fait testé):

primaryjoin=sqlalchemy.and_(
    film_table.c.country_id==film_table.c.country_id, 
    film_table.c.id!=film_table.c.id) 
+0

Pas tout à fait. Il ne remplace pas le film_table.c.id par? dans le sql généré. – Xuan

3

La solution la plus simple est de coder cette propriété vous-même au lieu de relation:

class Film(object): 
    @property 
    def same_country_films(self): 
     return [f for f in self.country.films if f!=self] 

Cette solution n'effectuera pas de requête distincte pour cette propriété lorsque vous accéderez à film.same_country_films et à country.films pendant la durée de vie de la session. La propriété ne peut pas être mise à jour comme vous pouvez habituellement le faire avec la relation, mais je doute que ce soit vraiment nécessaire.

La mauvaise chose est qu'elle est évaluée pour chaque accès (pas tellement de travail). Vous pouvez changer property décorateur à chaching un (comme cached_property dans werkzeug), mais alors la propriété ne reflétera pas les changements dans country.films après le premier accès à celui-ci.

+0

Merci pour la réponse. C'est une bonne solution au problème présenté. Pour être honnête, mon but réel est d'utiliser cet exemple de pays du film pour explorer comment fonctionne la relation. Est-il possible de résoudre le problème en utilisant la relation du tout? – Xuan

Questions connexes