Django Models / SQLAlchemy чрезмерно увеличен в размере! Кто-либо действительно модели Pythonic DB там?

"Сделайте вещи максимально простыми, но не более простыми".

Мы можем найти solution/s, которые фиксируют мир базы данных Python?

Обновление: 'lustdb' прототип был записан Alex Martelli - если Вы знаете какие-либо несколько легкие, высокоуровневые библиотеки базы данных с несколькими бэкендами, мы могли бы перенестись в меде сахара синтаксиса, взвесьтесь!

from someAmazingDB import *  
#we imported a smart model class and db object which talk to database adapter/s
class Task (model): 
    title = ''
    done = False #native types not a custom object we have to think about!

db.taskList = []
#or
db.taskList = expandableTypeCollection(Task) #not sure what this syntax would be

db['taskList'].append(Task(title='Beat old sql interfaces',done=False))
db.taskList.append(Task('Illustrate different syntax modes',True)) # ok maybe we should just use kwargs

#at this point it should be autosaved to a default db option

#by default we should be able to reload the console and access the default db:

>> from someAmazingDB import *
>> print 'Done tasks:'
>> for task in db.taskList:
>>     if task.done:
>>         print task.title
'Illustrate different syntax modes'

Я - поклонник Python, webPy и Cherry Py и KISS в целом.

Мы говорим автоматический Python с переводом типа SQL или NoSQL. Мы не должны полностью быть совместимым SQL! Просто масштабируемое подмножество или игнорирует его!

Изменения Re:model, нормально спрашивать разработчика, когда они пытаются изменить его или иметь ряд разумных значений по умолчанию.

Вот проблема: вышеупомянутый код должен работать с очень небольшой модификацией или необходимым размышлением. Почему мы должны выносить компромисс, когда мы знаем лучше?

Это - 2010, мы должны смочь кодировать масштабируемые, простые базы данных в нашем сне.

Если Вы думаете, что это важно, upvote!

6
задан 12 revs 7 June 2010 в 00:42
поделиться

7 ответов

Я был занят, вот он, выпущен под LGPL: http://github.com/lukestanley/lustdb

На данный момент он использует JSON в качестве бэкенда.

Это не та же кодовая база, которую сделал Алекс Мартелли. Я хотел сделать код более читабельным и многократно используемым с различными бэкендами и т.д.

В другом месте я работал над объектно-ориентированными элементами HTML. доступными в Python аналогичным образом, И над библиотекой для создания web.py более минималистичным.

Я думаю о том, как использовать все эти три элемента вместе с автоматическим построения прототипов MVC или умного отображения.

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

Пожалуйста, обратитесь к списку рассылки для тех, кто заинтересован.

1
ответ дан 8 December 2019 в 12:57
поделиться

Забудьте об ORM! Мне нравится ванильный SQL. Оболочки python, такие как psycopg2 для postgreSQL, выполняют автоматическое преобразование типов, предлагают неплохую защиту от SQL-инъекций, красивы и просты.

sql = "SELECT * FROM table WHERE id=%s"
data = (5,)
cursor.execute(sql, data)
1
ответ дан 8 December 2019 в 12:57
поделиться

То, что вы просите, не может быть сделано в Python 2. неважно, по очень конкретной причине. Вы хотите написать:

class Task(model): 
    title = ''
    isDone = False

В Python 2. что угодно, какой бы моделью она ни была, это не может никогда позволить вам предсказать какое-либо "упорядочивание" для двух полей, потому что семантика оператора class такова:

  1. выполнить тело, подготовив таким образом dict
  2. найти метакласс и запустить его специальные методы

Каким бы ни был метакласс, шаг 1 уничтожил любую предсказуемость порядка полей.

Поэтому желаемое использование позиционных параметров в фрагменте:

Task('Illustrate different syntax modes', True)

не может связать значения аргументов с различными полями модели. (Пытаться угадать по ассоциации типов - надеясь, что никакие два поля никогда не имеют одинакового типа - было бы еще более ужасно непитонично, чем ваше выраженное желание использовать db.tasklist и db['tasklist'] безразлично и взаимозаменяемо).

Одно из обратно несовместимых изменений в Python 3 было введено специально для решения подобных ситуаций. В Python 3 пользовательский метакласс может определить функцию __prepare__, которая выполняется перед "шагом 1" в приведенном выше упрощенном списке, и это позволяет ему иметь больше контроля над телом класса. В частности, цитируя PEP 3115...:

__prepare__ возвращает словареподобный объект, который используется для хранения определения членов класса во время оценки тела класса. Другими словами, тело класса оценивается как функциональный блок (точно так же, как и сейчас), за исключением того, что словарь локальных переменных заменяется словарем, возвращаемым из __prepare__. Этот словарный объект может быть обычным словарем или пользовательским отображением тип.

...

Примером может быть метакласс, который использует информацию о упорядочивании объявлений членов для создания C struct. Метакласс предоставляет пользовательский словарь, который просто сохраняет запись о порядок вставки.

Вы не хотите "создавать C struct", как в этом примере, но порядок полей имеет решающее значение (чтобы позволить использование позиционных параметров, которые вы хотите), поэтому пользовательский метакласс (полученный через базу model) будет иметь __prepare__ classmethod, возвращающий упорядоченный словарь. Это снимает конкретную проблему, но, конечно, только если вы готовы перевести весь ваш код, использующий этот "волшебный ORM", на Python 3. Готовы ли вы?

Когда это решено, вопрос заключается в том, какие операции с базой данных вы хотите выполнять и как. Ваш пример, конечно, совершенно не проясняет этого. Является ли имя атрибута taskList специальным, или любой другой атрибут, назначенный объекту db, должен быть "автосохранен" (по имени и, каким другим характеристикам?) и "автоизвлечен" при использовании? Должны ли существовать способы удаления сущностей, их изменения, определения их местоположения (иначе, чем по тому, что они когда-то были перечислены в одном атрибуте объекта db)? Как код вашего примера узнает, какой сервис БД использовать и как к нему аутентифицироваться (например, по имени пользователя и паролю), если требуется аутентификация?

Конкретные задачи, которые вы перечислили, будет несложно реализовать (например, поверх сервиса хранения Google App Engine, который не требует ни аутентификации, ни указания "какой сервис БД использовать"). Метакласс model будет интроспективно исследовать поля класса и генерировать GAE Model для класса, объект db будет использовать __setattr__ для установки atexit триггера для хранения конечного значения атрибута (как сущность в другом виде Model, конечно), и __getattr__ для получения информации об атрибуте из хранилища. Конечно, без дополнительной функциональности базы данных все это было бы довольно бесполезно;-).

Edit: я сделал небольшой прототип (Python 2.6, и основан на sqlite) и выложил его на http://www.aleax.it/lustdb.zip - это zip-файл размером 3K, включающий 225-строчный lustdb.py (слишком длинный, чтобы постить его здесь) и два небольших тестовых файла, примерно эквивалентных оригиналам OP: test0.py is...:

from lustdb import *  

class Task(Model): 
    title = ''
    done = False

db.taskList = []    
db.taskList.append(Task(title='Beat old sql interfaces', done=False))
db.taskList.append(Task(title='Illustrate different syntax modes', done=True))

и test1.p1 is...:

from lustdb import *

print 'Done tasks:'
for task in db.taskList:
    if task.done:
        print task

Запуск test0.py (на машине с доступным для записи каталогом /tmp -- т.е., любая Unix-y OS, или, в Windows, та, на которой mkdir \tmp был запущен в любое предыдущее время;-) не имеет никакого результата; после этого, запуск test1.py выводит:

Done tasks:
Task(done=True, title=u'Illustrate different syntax modes')

Обратите внимание, что это гораздо менее "безумно волшебно", чем примеры ОП, во многих отношениях, например. ...:

1. no (expletive delete) redundancy whereby `db.taskList` is a synonym of `db['taskList']`, only the sensible former syntax (attribute-access) is supported
2. no mysterious (and totally crazy) way whereby a `done` attribute magically becomes `isDone` instead midway through the code
3. no mysterious (and utterly batty) way whereby a `print task` arbitrarily (or magically?) picks and prints just one of the attributes of the task
4. no weird gyrations and incantations to allow positional-attributes in lieu of named ones (this one the OP agreed to)

Прототип, конечно, (как и положено прототипам;-) оставляет желать лучшего во многих отношениях (ясность, документация, модульные тесты, оптимизация, проверка и диагностика ошибок, переносимость между различными бэкендами, и особенно возможности БД, помимо тех, что подразумеваются в вопросе). Недостающие возможности БД многочисленны (например, оригинальные примеры ОП не дают возможности определить "первичный ключ" для модели, или любые другие виды ограничений уникальности, поэтому дубликаты могут быть многочисленны; и дальше становится только хуже;-). Тем не менее, для 225 строк (190 за вычетом пустых строк, комментариев и подстрочников;-), это не так уж плохо, по моему предвзятому мнению.

Конечно, правильным способом продолжить работу с этим проектом было бы инициировать новый lustdb open source проект на хостинге code.google. com (или на любом другом хорошем хостинге с трекером проблем, вики, поддержкой обзоров кода, онлайновым просмотром, поддержкой DVCS и т.д. и т.п.) - я бы сделал это сам, но я близок к пределу по количеству открытых проектов, которые я могу инициировать на code.google.com, и не хочу "сжигать" последние один или два таким образом;-).

BTW, lustdb имя для модуля - это игра слов с инициалами ОП (первые две буквы имени и фамилии), в традиции awk и друзей - я думаю, это звучит приятно (и большинство других очевидных имен, таких как simpledb и dumbdb взяты;-).

9
ответ дан 8 December 2019 в 12:57
поделиться

Как насчет того, чтобы вы дали пример того, насколько «простым» вы хотите, чтобы ваше «дело с базой данных» было, а затем я расскажу вам все, что необходимо для этой «простоты», чтобы начать работать?

(И из которых это все равно будет YOU, что будет необходимо для передачи информации / конфигурации движку интерфейса базы данных, где-то, каким-то образом.)

Назовем только один пример:

Если ядро управления базами данных является каким-то внешним компьютером, с которым вы или ваше приложение взаимодействуете по IP или какому-либо подобному, нет никакого способа обойти тот факт, что IP-идентификатор того места, где работает это ядро СУБД, должен быть предоставлен клиентом интерфейса базы данных вашего приложения, где-то, как-нибудь. Независимо от того, будет ли это явно представлено в коде или нет.

1
ответ дан 8 December 2019 в 12:57
поделиться

Чем больше я думаю, тем более актуальной кажется модель работы Smalltalk. В самом деле, OP, возможно, не продвинулся достаточно далеко, используя термин «база данных» для описания того, что не должно иметь нужды в именовании.

У работающего интерпретатора Python есть куча объектов, которые живут в памяти. Их взаимосвязи могут быть сколь угодно сложными, но пространства имен и «теги», к которым привязаны объекты, очень гибкие. И поскольку pickle может явно сериализовать произвольные структуры для сохранения, не кажется, что уместно рассматривать каждый интерпретатор Python, живущий в этом объектном пространстве. Почему это объектное пространство должно испаряться с приближением переводчика? Семантически это можно рассматривать как расширение связанных словарей anydbm . И поскольку почти все в Python похоже на словарь, механизм почти уже существует.

Я думаю, что это может быть общая модель, которую Алекс Мартелли предлагал выше, было бы неплохо сказать что-то вроде:

class Book:
    def __init__(self, attributes):
        self.attributes = attributes
    def __getattr__(....): pass

$ python
>>> import book
>>> my_stuff.library = {'garp': 
    Book({'author': 'John Irving', 'title': 'The World According to Garp', 
      'isbn': '0-525-23770-4', 'location': 'kitchen table', 
      'bookmark': 'page 127'}),
    ...
    }
>>> exit

[где-нибудь на следующей неделе]

$ python
>>> import my_stuff
>>> print my_stuff.library['garp'].location
'kitchen table'
# or even
>>> for book in my_stuff.library where book.location.contains('kitchen'):
   print book.title

Я не знаю, назовете ли вы получившийся язык Python, но похоже, что это не так сложно реализовать и делает резервное хранилище эквивалентным активному хранилищу.

Существует естественное противоречие между внутренней структурой, навязываемой - а иногда и желаемой - РСУБД, и довольно свободной формой взгляда на пупок, представленной здесь, но базы данных NoSQLy уже приближаются к модели адресуемой памяти и, вероятно, лучше соответствуют тому, как мы думаем. следить за вещами. И наоборот, вы не захотите хранить все корпоративные заказы на закупку в такой системе хранения, но, возможно, сможете.

1
ответ дан 8 December 2019 в 12:57
поделиться

Как насчет использования Эликсира ?

2
ответ дан 8 December 2019 в 12:57
поделиться

Думаю, вам стоит попробовать ZODB . Это объектно-ориентированная база данных, предназначенная для хранения объектов Python. Его API очень близок к примеру, который вы указали в своем вопросе, просто просмотрите посмотрите в руководстве.

3
ответ дан 8 December 2019 в 12:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: