Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SQLAlchemy模型不可预测地分配关系_Python_Postgresql_Sqlalchemy_Data Modeling_Relationships - Fatal编程技术网

Python SQLAlchemy模型不可预测地分配关系

Python SQLAlchemy模型不可预测地分配关系,python,postgresql,sqlalchemy,data-modeling,relationships,Python,Postgresql,Sqlalchemy,Data Modeling,Relationships,我正在创建一个数据库User模型,它可以属于几个Traits。下面的脚本复制了一个我不理解的奇怪行为——在提交新行之后,关系以一种不可预测的方式将Traits附加到用户s 我希望能够将1+特征附加到用户,并且我希望用户能够共享特征 但在本例中,当一个特征在用户之间共享时,该特征有时附加到用户1,有时附加到用户2。我怎样才能让用户分享自己的特点呢 import enum from sqlalchemy import Column, Integer, String from sqlalchemy.e

我正在创建一个数据库
User
模型,它可以属于几个
Trait
s。下面的脚本复制了一个我不理解的奇怪行为——在提交新行之后,关系以一种不可预测的方式将
Trait
s附加到
用户
s

我希望能够将1+特征附加到用户,并且我希望用户能够共享特征

但在本例中,当一个特征在用户之间共享时,该特征有时附加到用户1,有时附加到用户2。我怎样才能让用户分享自己的特点呢

import enum
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Enum, UniqueConstraint, ForeignKey
from sqlalchemy.orm import backref, relationship, validates
Base = declarative_base()

class TraitName(enum.Enum):
    happy = 0
    mad = 1
    full = 2

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    username = Column(String(80), unique=True, nullable=False)
    traits = relationship("Trait")
    def __repr__(self):
        return self.username + str(traits)

class Trait(Base):
    __tablename__ = 'traits'

    id = Column(Integer, primary_key=True)
    name = Column(Enum(TraitName), nullable=False)
    user_id = Column(Integer, ForeignKey('users.id'))
    __table_args__ = (UniqueConstraint('name', 'user_id', name='_user_trait'),)
    def __repr__(self):
        return str(self.name)
当我多次运行此脚本时

from sqlalchemy import create_engine
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

engine = create_engine('postgresql://postgres@localhost:5420/test_db')
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
session = Session(engine)

user1 = User(username="bob")
user2 = User(username="ann")
happy_trait = Trait(name=TraitName.happy)
full_trait = Trait(name=TraitName.full)
user1.traits.extend([full_trait, happy_trait])
user2.traits.append(happy_trait)
session.add_all([user1, user2])
session.commit()
print([t.traits for t in session.query(User).all()])
print(session.query(Trait.user_id).all())
print(session.query(Trait).filter(Trait.user_id.in_((1,))).all())
session.close()
不同的结果:

要么:

[[TraitName.full, TraitName.happy], []] # Users' traits
[(1,), (1,)]                            # Traits' user_ids
[TraitName.full, TraitName.happy]       # Traits with uers_id 1

因此,我想理解为什么
特质
会被不可预测地分配。我如何为我的用户和特征建模以避免这种情况——也许这不是将特征附加到用户的合适模式


另外,如果可能的话(我想一切都是可能的),我希望在
User
上有两个字段:
inactive\u traits
active\u traits
字段。但无论如何,我首先要弄清楚如何让一系列特性发挥作用。

你给你的类命名不好,这导致你用错了它们

你的TraitName实际上是你的Trait,它应该被共享,而你的Trait实际上是一个UserTrait,它不能在用户之间共享,但是你尝试在他们之间共享实例

我会做以下几点:

import enum
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm, Enum, ForeignKey, create_engine

Base = declarative_base()

class Trait(enum.Enum):
    happy = 0
    mad = 1
    full = 2

class User(Base):
    __tablename__ = 'users'

    user_id = Column(Integer, primary_key=True)
    username = Column(String(80), unique=True, nullable=False)
    traits = orm.relationship("UserTrait")
    def __repr__(self):
        return self.username + str(self.traits)

class UserTrait(Base):
    __tablename__ = 'usertraits'

    user_id = Column(Integer, ForeignKey('users.user_id'), primary_key=True)
    trait = Column(Enum(Trait), primary_key=True)

    def __repr__(self):
        return str([self.user_id, self.trait])

def __main__():

    engine = create_engine('postgresql:///?host=/var/run/postgresql/', echo=False)
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    session = orm.Session(engine)

    user1 = User(username="bob")
    user2 = User(username="ann")
    user1.traits.extend([UserTrait(trait=Trait.full), UserTrait(trait=Trait.happy)])
    user2.traits.append(UserTrait(trait=Trait.happy))
    session.add_all([user1, user2])
    session.commit()
    print([t.traits for t in session.query(User).all()])
    print(session.query(UserTrait.user_id).all())
    print(session.query(UserTrait).filter(UserTrait.user_id.in_((1,))).all())
    session.close()

if __name__ == "__main__":
    __main__()
import enum
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import orm, Enum, ForeignKey, create_engine

Base = declarative_base()

class Trait(enum.Enum):
    happy = 0
    mad = 1
    full = 2

class User(Base):
    __tablename__ = 'users'

    user_id = Column(Integer, primary_key=True)
    username = Column(String(80), unique=True, nullable=False)
    traits = orm.relationship("UserTrait")
    def __repr__(self):
        return self.username + str(self.traits)

class UserTrait(Base):
    __tablename__ = 'usertraits'

    user_id = Column(Integer, ForeignKey('users.user_id'), primary_key=True)
    trait = Column(Enum(Trait), primary_key=True)

    def __repr__(self):
        return str([self.user_id, self.trait])

def __main__():

    engine = create_engine('postgresql:///?host=/var/run/postgresql/', echo=False)
    Base.metadata.drop_all(engine)
    Base.metadata.create_all(engine)
    session = orm.Session(engine)

    user1 = User(username="bob")
    user2 = User(username="ann")
    user1.traits.extend([UserTrait(trait=Trait.full), UserTrait(trait=Trait.happy)])
    user2.traits.append(UserTrait(trait=Trait.happy))
    session.add_all([user1, user2])
    session.commit()
    print([t.traits for t in session.query(User).all()])
    print(session.query(UserTrait.user_id).all())
    print(session.query(UserTrait).filter(UserTrait.user_id.in_((1,))).all())
    session.close()

if __name__ == "__main__":
    __main__()