Делал как-то подобное (
theorytesting.com напр., хотя и не совсем то же), и ZODB удобен для подобных вещей. Думаю, можно сделать так:
1) Общий контейнер для тестов.
2) В него можно добавлять тесты.
3) Каждый тест - это контейнер, но с дополнительными полями title и description и чего-то там еще.
В него можно добавлять вопросы - это объекты (Persistent, Contained). Поскольку ответы на вопросы могут иметь разную схему, то сделать разные типы, и потом можно добавлять новые.
4) Объект-вопрос имеет схему (пример для варианта список-строк):
class IQuestionBase(Interface):
question = Text(title=u"Сюда создатель теста записывает вопрос")
class IQuestionWithListAnswer(IQuestionBase):
answersTest = List(
title=u"Это список возможных ответов в текстовом виде"
value_type=TextLine())
answersRight = List(
title=u"Это список правильных ответов",
value_type=TextLine())
4) В сайт-менеджер добавить zope.session.session.PersistentSessionDataContainer, зарегистрировать как именованную локальную утилиту с именем FOO_BAR
5) При старте тестирования случайно или еще по какому-то алгоритму подбираются список вопросов (или все) и их UIDs кладутся в
сессию:
session = ISession(self.request)
sessionData = session[FOO_BAR]
sessionData[QEUSTIONS] = questionUIDS
6) Форма для отвечающих перебирает объекты, выталкивая их UIDS из sessionData, берет у объекта интерфейс и поле answerTest и по нему строит форму, сохраняя результат в сессии. Так как при построении формы понадобится другой field (в вышенауказанном примере - нужно Choice) - то построить словарь соответствий между используемыми field'ами.
Вот так. А можно еще как-нибудь, согласен что вариантов куча.