Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/67.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
SQLAlchemy插入多对一条目_Sqlalchemy_Many To One - Fatal编程技术网

SQLAlchemy插入多对一条目

SQLAlchemy插入多对一条目,sqlalchemy,many-to-one,Sqlalchemy,Many To One,抱歉,如果这是一个新手问题,但是关于的文档似乎没有涵盖这一点。我一直在寻找类似于How to Insert/Add Data to Your Tables(如何向表插入/添加数据)部分的内容,但是在所示的示例中,这始终是一个独特的插入 基本上,我想用本地机器上的数据填充数据库。为了简单起见,我已经将下面所示的示例构建成一个MWE来说明这个问题。这个问题由两个名为Price和Currency的表组成,实现是以声明式方式完成的 model.py 从sqlalchemy导入列,整数,字符串 从sql

抱歉,如果这是一个新手问题,但是关于的文档似乎没有涵盖这一点。我一直在寻找类似于How to Insert/Add Data to Your Tables(如何向表插入/添加数据)部分的内容,但是在所示的示例中,这始终是一个独特的插入

基本上,我想用本地机器上的数据填充数据库。为了简单起见,我已经将下面所示的示例构建成一个MWE来说明这个问题。这个问题由两个名为Price和Currency的表组成,实现是以声明式方式完成的

model.py

从sqlalchemy导入列,整数,字符串 从sqlalchemy导入Float、BigInteger、ForeignKey 从sqlalchemy.orm导入关系,backref 从sqlalchemy.ext.declarative导入声明性基础 Base=声明性的\u Base 类别库: __tablename_uu='货币' id=ColumnInteger,主键=True 单位=ColumnString16,唯一=True 定义初始自我,单位: self.unit=单位 类别价格基数: __tablename_uuu=‘价格’ id=ColumnBigInteger,主键=True currency_id=ColumnInteger,ForeignKeyCurrency.id,nullable=False currency=relationshipCurrency,backref=currency.id hour1=列浮点 hour2=列浮点 定义初始自我,小时1,小时2: self.hour1=hour1 self.hour2=hour2 目前,我正在使用以下代码填充数据库:

script.py

从sqlalchemy导入创建引擎 从sqlalchemy.orm导入作用域的_会话,sessionmaker 从模型导入* 引擎=创建引擎'sqlite:///example.db,echo=True db_session=scoped_sessionsMakerautommit=False, 自动刷新=错误, 绑定=引擎 会话=db_会话 Base.metadata.create_allengine oPrice=价格2.5,2.5 oPrice.currency=货币欧元 session.addoPrice t价格=价格5.5,1.5 tPrice.currency=CurrencyEUR session.addtPrice session.commit 这会产生一个错误

sqlalchemy.exc.IntegrityError:IntegrityError列单位不唯一u'插入货币单位值“EUR”


填充数据库的最佳策略是什么,以确保Currency.id和Price.Currency\u id映射正确?我应该让模型类在初始化之前寻找唯一性吗?我应该在与另一个表关联时这样做吗?

最简单的解决方案是使用货币代码作为货币中的主键,使用外键作为价格中的外键。那你就可以

price.currency_id = "EUR"

这也使您的数据库表更具可读性—例如,您将不会有28342,而是“GBP”。

最简单的解决方案是使用货币代码作为货币的主键,而使用外键作为价格。那你就可以

price.currency_id = "EUR"

这也使您的数据库表更具可读性-例如,您将不会有28342,而是“GBP”。

我支持Antti的建议,因为货币有标准代码,如“INR”、“USD”等,您可以将货币代码作为主键

或者,如果要保留数字主键,则其中一个选项是:

根据上面链接中的配方编辑添加示例,该配方具有DeCartor类

database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:///example.db', echo=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                     autoflush=False,
                                     bind=engine))
model.py

from sqlalchemy import Column, Integer, String
from sqlalchemy import Float, BigInteger, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base

from database import db_session

Base = declarative_base()

def _unique(session, cls, hashfunc, queryfunc, constructor, arg, kw):
    cache = getattr(session, '_unique_cache', None)
    if cache is None:
        session._unique_cache = cache = {}

    key = (cls, hashfunc(*arg, **kw))
    if key in cache:
        return cache[key]
    else:
        with session.no_autoflush:
            q = session.query(cls)
            q = queryfunc(q, *arg, **kw)
            obj = q.first()
            if not obj:
                obj = constructor(*arg, **kw)
                session.add(obj)
        cache[key] = obj
        return obj

def unique_constructor(scoped_session, hashfunc, queryfunc):
    def decorate(cls):
        def _null_init(self, *arg, **kw):
            pass
        def __new__(cls, bases, *arg, **kw):
            # no-op __new__(), called
            # by the loading procedure
            if not arg and not kw:
                return object.__new__(cls)

            session = scoped_session()

            def constructor(*arg, **kw):
                obj = object.__new__(cls)
                obj._init(*arg, **kw)
                return obj

            return _unique(
                    session,
                    cls,
                    hashfunc,
                    queryfunc,
                    constructor,
                    arg, kw
               )

      # note: cls must be already mapped for this part to work
        cls._init = cls.__init__
        cls.__init__ = _null_init
        cls.__new__ = classmethod(__new__)
        return cls

    return decorate




@unique_constructor(
db_session,
lambda unit: unit,
lambda query, unit: query.filter(Currency.unit == unit)
)
class Currency(Base):
    __tablename__ = 'Currency'

    id = Column(Integer, primary_key=True)
    unit = Column(String(16), unique=True)

    def __init__(self, unit):
        self.unit = unit

class Price(Base):
    __tablename__ = 'Price'

    id = Column(BigInteger, primary_key=True)

    currency_id = Column(Integer, ForeignKey("Currency.id"), nullable=False)
    currency = relationship("Currency", backref="Currency.id")

    hour1 = Column(Float)
    hour2 = Column(Float)

    def __init__(self, hour1, hour2):
        self.hour1 = hour1
        self.hour2 = hour2
script.py:

from model import *
from database import engine, db_session as session

Base.metadata.create_all(engine)

oPrice = Price(2.5, 2.5)
oPrice.currency = Currency("EUR")
session.add(oPrice)

tPrice = Price(5.5, 1.5)
tPrice.currency = Currency("EUR")
session.add(tPrice)

session.commit()

我支持Antti的建议,因为货币有标准代码,如“INR”、“USD”等,所以可以将货币代码作为主键

或者,如果要保留数字主键,则其中一个选项是:

根据上面链接中的配方编辑添加示例,该配方具有DeCartor类

database.py

from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker

engine = create_engine('sqlite:///example.db', echo=True)
db_session = scoped_session(sessionmaker(autocommit=False,
                                     autoflush=False,
                                     bind=engine))
model.py

from sqlalchemy import Column, Integer, String
from sqlalchemy import Float, BigInteger, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declarative_base

from database import db_session

Base = declarative_base()

def _unique(session, cls, hashfunc, queryfunc, constructor, arg, kw):
    cache = getattr(session, '_unique_cache', None)
    if cache is None:
        session._unique_cache = cache = {}

    key = (cls, hashfunc(*arg, **kw))
    if key in cache:
        return cache[key]
    else:
        with session.no_autoflush:
            q = session.query(cls)
            q = queryfunc(q, *arg, **kw)
            obj = q.first()
            if not obj:
                obj = constructor(*arg, **kw)
                session.add(obj)
        cache[key] = obj
        return obj

def unique_constructor(scoped_session, hashfunc, queryfunc):
    def decorate(cls):
        def _null_init(self, *arg, **kw):
            pass
        def __new__(cls, bases, *arg, **kw):
            # no-op __new__(), called
            # by the loading procedure
            if not arg and not kw:
                return object.__new__(cls)

            session = scoped_session()

            def constructor(*arg, **kw):
                obj = object.__new__(cls)
                obj._init(*arg, **kw)
                return obj

            return _unique(
                    session,
                    cls,
                    hashfunc,
                    queryfunc,
                    constructor,
                    arg, kw
               )

      # note: cls must be already mapped for this part to work
        cls._init = cls.__init__
        cls.__init__ = _null_init
        cls.__new__ = classmethod(__new__)
        return cls

    return decorate




@unique_constructor(
db_session,
lambda unit: unit,
lambda query, unit: query.filter(Currency.unit == unit)
)
class Currency(Base):
    __tablename__ = 'Currency'

    id = Column(Integer, primary_key=True)
    unit = Column(String(16), unique=True)

    def __init__(self, unit):
        self.unit = unit

class Price(Base):
    __tablename__ = 'Price'

    id = Column(BigInteger, primary_key=True)

    currency_id = Column(Integer, ForeignKey("Currency.id"), nullable=False)
    currency = relationship("Currency", backref="Currency.id")

    hour1 = Column(Float)
    hour2 = Column(Float)

    def __init__(self, hour1, hour2):
        self.hour1 = hour1
        self.hour2 = hour2
script.py:

from model import *
from database import engine, db_session as session

Base.metadata.create_all(engine)

oPrice = Price(2.5, 2.5)
oPrice.currency = Currency("EUR")
session.add(oPrice)

tPrice = Price(5.5, 1.5)
tPrice.currency = Currency("EUR")
session.add(tPrice)

session.commit()

我有一个模糊的记忆,我看到了一个更好的模式,没有在Trac页面上,但找不到它…如果你能举个例子,我会非常感激。我有一个模糊的记忆,我看到了一个更好的模式,没有在Trac页面上,但找不到它…如果你能举个例子,我真的很感激。对于这个简化的问题,我同意,但我有多个表,价格表中的条目有多列,不太容易取整。对于这个简化的问题,我同意,但我有多个表,价格表中的条目有多列,不太容易取整。