Как мне кодировать эти отношения в SQLAlchemy? - PullRequest
0 голосов
/ 13 мая 2010

Я новичок в SQLAlchemy (и в этом отношении SQL).Я не могу понять, как закодировать идею, которая у меня в голове.

Я создаю базу данных результатов теста производительности.

Тестовый прогон состоит из типа теста ичисло (это класс TestRun ниже)

Набор тестов состоит из строки версии тестируемого программного обеспечения и одного или нескольких объектов TestRun (это класс TestSuite ниже).

Тестовая версиясостоит из всех наборов тестов с указанным именем версии.

Вот мой код, настолько простой, насколько я могу это сделать:

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, backref, sessionmaker

Base = declarative_base()

class TestVersion (Base):
    __tablename__ = 'versions'
    id = Column (Integer, primary_key=True)
    version_name = Column (String)

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


class TestRun (Base):
    __tablename__ = 'runs'
    id = Column (Integer, primary_key=True)
    suite_directory = Column (String, ForeignKey ('suites.directory'))
    suite = relationship ('TestSuite', backref=backref ('runs', order_by=id))
    test_type = Column (String)
    rate = Column (Integer)

    def __init__ (self, test_type, rate):
        self.test_type = test_type
        self.rate = rate


class TestSuite (Base):
    __tablename__ = 'suites'
    directory = Column (String, primary_key=True)
    version_id = Column (Integer, ForeignKey ('versions.id'))
    version_ref = relationship ('TestVersion', backref=backref ('suites', order_by=directory))
    version_name = Column (String)

    def __init__ (self, directory, version_name):
        self.directory = directory
        self.version_name = version_name


# Create a v1.0 suite
suite1 = TestSuite ('dir1', 'v1.0')
suite1.runs.append (TestRun ('test1', 100))
suite1.runs.append (TestRun ('test2', 200))

# Create a another v1.0 suite
suite2 = TestSuite ('dir2', 'v1.0')
suite2.runs.append (TestRun ('test1', 101))
suite2.runs.append (TestRun ('test2', 201))

# Create another suite
suite3 = TestSuite ('dir3', 'v2.0')
suite3.runs.append (TestRun ('test1', 102))
suite3.runs.append (TestRun ('test2', 202))

# Create the in-memory database
engine = create_engine ('sqlite://')
Session = sessionmaker (bind=engine)
session = Session()
Base.metadata.create_all (engine)

# Add the suites in
version1 = TestVersion (suite1.version_name)
version1.suites.append (suite1)
session.add (suite1)

version2 = TestVersion (suite2.version_name)
version2.suites.append (suite2)
session.add (suite2)

version3 = TestVersion (suite3.version_name)
version3.suites.append (suite3)
session.add (suite3)

session.commit()

# Query the suites
for suite in session.query (TestSuite).order_by (TestSuite.directory):
    print "\nSuite directory %s, version %s has %d test runs:" % (suite.directory, suite.version_name, len (suite.runs))
    for run in suite.runs:
        print "  Test '%s', result %d" % (run.test_type, run.rate)

# Query the versions
for version in session.query (TestVersion).order_by (TestVersion.version_name):
    print "\nVersion %s has %d test suites:" % (version.version_name, len (version.suites))
    for suite in version.suites:
        print "  Suite directory %s, version %s has %d test runs:" % (suite.directory, suite.version_name, len (suite.runs))
        for run in suite.runs:
            print "    Test '%s', result %d" % (run.test_type, run.rate)

Вывод этой программы:

Suite directory dir1, version v1.0 has 2 test runs:
  Test 'test1', result 100
  Test 'test2', result 200

Suite directory dir2, version v1.0 has 2 test runs:
  Test 'test1', result 101
  Test 'test2', result 201

Suite directory dir3, version v2.0 has 2 test runs:
  Test 'test1', result 102
  Test 'test2', result 202

Version v1.0 has 1 test suites:
  Suite directory dir1, version v1.0 has 2 test runs:
    Test 'test1', result 100
    Test 'test2', result 200

Version v1.0 has 1 test suites:
  Suite directory dir2, version v1.0 has 2 test runs:
    Test 'test1', result 101
    Test 'test2', result 201

Version v2.0 has 1 test suites:
  Suite directory dir3, version v2.0 has 2 test runs:
    Test 'test1', result 102
    Test 'test2', result 202

Это не правильно, так как есть два объекта TestVersion с именем 'v1.0'.Я решил эту проблему, добавив закрытый список объектов TestVersion и функцию для поиска подходящего:

versions = []
def find_or_create_version (version_name):

    # Find existing
    for version in versions:
        if version.version_name == version_name:
            return (version)

    # Create new
    version = TestVersion (version_name)
    versions.append (version)
    return (version)

Затем я изменил свой код, добавляющий записи, чтобы использовать его:

# Add the suites in
version1 = find_or_create_version (suite1.version_name)
version1.suites.append (suite1)
session.add (suite1)

version2 = find_or_create_version (suite2.version_name)
version2.suites.append (suite2)
session.add (suite2)

version3 = find_or_create_version (suite3.version_name)
version3.suites.append (suite3)
session.add (suite3)

Теперь вывод - это то, что я хочу:

Suite directory dir1, version v1.0 has 2 test runs:
  Test 'test1', result 100
  Test 'test2', result 200

Suite directory dir2, version v1.0 has 2 test runs:
  Test 'test1', result 101
  Test 'test2', result 201

Suite directory dir3, version v2.0 has 2 test runs:
  Test 'test1', result 102
  Test 'test2', result 202

Version v1.0 has 2 test suites:
  Suite directory dir1, version v1.0 has 2 test runs:
    Test 'test1', result 100
    Test 'test2', result 200
  Suite directory dir2, version v1.0 has 2 test runs:
    Test 'test1', result 101
    Test 'test2', result 201

Version v2.0 has 1 test suites:
  Suite directory dir3, version v2.0 has 2 test runs:
    Test 'test1', result 102
    Test 'test2', result 202

Мне кажется, это неправильно;Неправильно, что я вручную отслеживаю уникальные имена версий и вручную добавляю наборы к соответствующим объектам TestVersion.

Является ли этот код даже близким к правильному?

И что происходит, когда я не собираю всю базу данных с нуля, как в этом примере.Если база данных уже существует, нужно ли запрашивать таблицу TestVersion базы данных, чтобы обнаружить уникальные имена версий?

Заранее спасибо.Я знаю, что это большой код, и я ценю помощь.

1 Ответ

1 голос
/ 13 мая 2010

Я не могу понять, каков ваш вопрос, во многом потому, что вы его не уточнили.Возможно, ваш вопрос касается схемы и, возможно, соответствующей ей объектно-реляционной модели.Итак, вот ORM, разделенный до его ядра:

class TestVersion(Base):
    __tablename__ = 'versions'
    id = Column(Integer, primary_key=True)
    name = Column(String)

class TestSuite(Base):
    __tablename__ = 'suites'
    directory = Column(String, primary_key=True)
    version = Column(Integer, ForeignKey ('versions.id'))

    parent = relationship(TestVersion, backref=backref('suites',
        order_by=directory))

class TestRun(Base):
    __tablename__ = 'runs'
    id = Column(Integer, primary_key=True)
    directory = Column(String, ForeignKey ('suites.directory'))

    parent = relationship(TestSuite, backref=backref('runs',
         order_by=id))

Я взял на себя много вольности с вашей декларацией: выбрасывая столбцы, не связанные с вашей проблемой, переупорядочивая объявления, чтобы сделать цепочку зависимостей более очевидной и т. Д.Возможно, с помощью этой уменьшенной модели вы можете лучше описать свою проблему.

Кроме того, стандарты кодирования, такие как PEP 8 , существуют по причине: если вы хотите, чтобы ваш код был понятен другим, используйте 4отступы между пробелами и исключение пробелов между Именем и '(', ограничением строк до 79 символов и т. д. Да, это кажется педантичным, но вы просто столкнулись с ситуацией, когда вашему читателю было труднее читать ваш код, чем хотелось бы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...