web-dev-qa-db-fra.com

sqlalchemy unique sur plusieurs colonnes

Disons que j'ai une classe qui représente les lieux. Les emplacements "appartiennent" aux clients. Les emplacements sont identifiés par un code Unicode de 10 caractères. Le "code d'emplacement" doit être unique parmi les emplacements d'un client spécifique.

The two below fields in combination should be unique
customer_id = Column(Integer,ForeignKey('customers.customer_id')
location_code = Column(Unicode(10))

Donc, si j'ai deux clients, le client "123" et le client "456". Ils peuvent tous les deux avoir un emplacement appelé "principal" mais aucun ne peut avoir deux emplacements appelés principal.

Je peux gérer cela dans la logique métier mais je veux m'assurer qu'il n'y a aucun moyen d'ajouter facilement l'exigence dans sqlalchemy. L'option unique = True ne semble fonctionner que lorsqu'elle est appliquée à un champ spécifique et la table entière n'aurait alors qu'un code unique pour tous les emplacements.

138
Ominus

Extrait de la documentation de la Column:

unique - Lorsque True, indique que cette colonne contient une contrainte unique, ou si index est également True, indique que l'index doit être créé avec l'indicateur unique. Pour spécifier plusieurs colonnes dans la contrainte/index ou pour spécifier un nom explicite, utilisez explicitement les constructions niqueConstraint ou Index .

Comme ceux-ci appartiennent à une table et non à une classe mappée, on les déclare dans la définition de la table, ou en utilisant déclarative comme dans le __table_args__:

# version1: table definition
mytable = Table('mytable', meta,
    # ...
    Column('customer_id', Integer, ForeignKey('customers.customer_id')),
    Column('location_code', Unicode(10)),

    UniqueConstraint('customer_id', 'location_code', name='uix_1')
    )
# or the index, which will ensure uniqueness as well
Index('myindex', mytable.c.customer_id, mytable.c.location_code, unique=True)


# version2: declarative
class Location(Base):
    __table= 'locations'
    id = Column(Integer, primary_key = True)
    customer_id = Column(Integer, ForeignKey('customers.customer_id'), nullable=False)
    location_code = Column(Unicode(10), nullable=False)
    __table_args__ = (UniqueConstraint('customer_id', 'location_code', name='_customer_location_uc'),
                     )
240
van