A pure Python Database Abstraction Layer

Related tags



pyDAL is a pure Python Database Abstraction Layer.

It dynamically generates the SQL/noSQL in realtime using the specified dialect for the database backend, so that you do not have to write SQL code or learn different SQL dialects (the term SQL is used generically), and your code will be portable among different types of databases.

pyDAL comes from the original web2py's DAL, with the aim of being compatible with any Python program. pyDAL doesn't require web2py and can be used in any Python context.

pip version Build Status MS Build Status Coverage Status API Docs Status


You can install pyDAL using pip:

pip install pyDAL

Usage and Documentation

Here is a quick example:

>>> from pydal import DAL, Field
>>> db = DAL('sqlite://storage.db')
>>> db.define_table('thing', Field('name'))
>>> db.thing.insert(name='Chair')
>>> query = db.thing.name.startswith('C')
>>> rows = db(query).select()
>>> print rows[0].name
>>> db.commit()

The complete documentation is available on http://www.web2py.com/books/default/chapter/29/06/the-database-abstraction-layer

What's in the box?

A little taste of pyDAL features:

  • Transactions
  • Aggregates
  • Inner Joins
  • Outer Joins
  • Nested Selects

Which databases are supported?

pyDAL supports the following databases:

  • SQLite
  • MySQL
  • PostgreSQL
  • FireBird
  • Oracle
  • DB2
  • Ingres
  • Sybase
  • Informix
  • Teradata
  • Cubrid
  • IMAP
  • MongoDB


pyDAL is released under the BSD-3c License. For further details, please check the LICENSE file.

  • encoding error writing unicode string to postgre

    encoding error writing unicode string to postgre

    Taking the effort of posting here what is reported on web2py. I feel that those DAL bugs are never seen as a priority if not posted here.........


    opened by niphlod 39
  • Problem with collision check in merge_tablemaps

    Problem with collision check in merge_tablemaps

    I'm struggling with this: https://github.com/web2py/pydal/blob/master/pydal/helpers/methods.py#L83

    ...as it requires identity of aliased Table instances, and hence fails if the same aliasing happens twice, i.e.:

    table.with_alias("alias") is not table.with_alias("alias")

    ...even though it's the same table, and the same alias, and consequently the same SQL.

    Why does it have to be this way - wouldn't it be good enough to ensure that the DAL name of both tables is the same (i.e. that they refer to the same original table)? Do they really have to be exactly the same Python object?

    opened by nursix 37
  • Refactoring


    As introduced on the group (https://groups.google.com/forum/#!topic/web2py-developers/zw6-bFpe96s) this is a major refactoring of the code base.

    Feedbacks and comments are welcome.

    Intentions and the rationale:

    • Stop using the BaseAdapter as a super-collector (sometimes taking place of SQLite – ed. note)
    • Better using inheritance between classes
    • Simplify the writing of new adapters (and increase the contributions)
    • De-uglify a lot of the code making it simpler to understand and debug
    • Allowing to easily implement performance optimizations

    Refactoring steps:

    • [x] BaseAdapter re-structuring
    • [x] Better SQLAdapter and NoSQLAdapter
    • [x] Base dialects structure
    • [x] Base parsers structure
    • [x] Base representers structure
    • [x] Migrations separation from base adapter
    • [x] SQLite and Spatialite adapters
    • [x] Postgresql adapter
    • [x] Postgresql 2/new adapter
    • [x] MySQL adapter
    • [x] MSSQL adapter
    • [x] jdbc versions of adapters
    • [x] Review of NoSQLAdapter
    • [x] MongoDB Adapter
    • [x] Other SQL adapters
    • [x] Other NoSQL adapters
    • [x] Final code cleaning

    Changes from 16.03:

    • Postgre adapter no longer parse datetime objects
    • MSSQL2Adapter no longer exists since was the same of MSSQLNAdapter (but the uri is still valid)
    • Includes fix for #296
    • BaseAdapter.connection and BaseAdapter.cursor are now thread safe
    • Removed _lastsql in adapters since not thread safe
    • Empty values for ObjectId fields in MongoAdapter now are stored (and returned) as None instead of a fake ObjectId converted to integer 0
    opened by gi0baro 36
  • Joinable subselects

    Joinable subselects

    This changeset implements subselect objects that can be used in a join like a virtual table or passed to Expression.belongs(). Subselect objects can be created using Set.nested_select() which accepts the same arguments as regular select(). One additional argument, correlated, determines whether the subselect may reference tables from parent select (defaults to True which means referencing is permitted). Example usage:

    total = table1.field2.sum().with_alias('total')
    sub1 = db(table1.field2 != None).nested_select(table1.field1, total, groupby=table1.field1)
    sub1 = sub1.with_alias('tmp')
    result1 = db(table2.field1 == sub1.field1).select(table2.ALL, sub1.total)
    total = table1.field2.sum().with_alias('total')
    sub2 = db(table1.field2 != None).nested_select(total, groupby=table1.field1)
    result2 = db(table2.field2.belongs(sub2)).select(table2.ALL)

    I'm opening this pull request early for design discussion. Unit tests for Python 2.7, 3.4 & 3.5 and SQLite, MySQL and PostgreSQL are passing on my machine but there's still work to do. Comments and suggestions are appreciated.

    Design changes

    • Adapters and dialects must no longer resolve table names over and over through DAL.__getitem__(). They must pass Table/Select objects around.
    • New methods for class Table:
      • query_name() - Full table name for query FROM clause, including possible alias.
      • query_alias() - The appropriate string that identifies the table throughout a query (e.g. for building fully qualified field names).
    • Rows.__init__() now takes additional argument - list of Field/Expression objects corresponding to columns
    • BaseAdapter._select() now returns a Select object instead of string
    • BaseAdapter.tables() now returns a dict mapping table names to table objects instead of name list.
    • BaseAdapter.common_filter() now accepts table objects as well as table names.
    • many other BaseAdapter internal methods now take or return table objects instead of table names.
    new feature 
    opened by nextghost 36
  • Table name bugfixes

    Table name bugfixes

    This changeset fixes update()/delete() on aliased tables and bugs caused by using the wrong table/field name in various queries (especially in migrator).

    Changes in class Table

    • Table._ot has been renamed to Table._dalname and it is always set to the original internal table name.
    • Table._rname now defaults to quoted Table._dalname (except when the table is not associated with any database, only then it gets set to None).
    • Added Table._raw_rname which is the unquoted version of _rname (for generating extra identifers based on the backend table name, e.g. sequence names).
    • Table.sqlsafe renamed to sql_shortref.
    • Table.sqlsafe_alias renamed to sql_fullref.

    Example where they belong in a query: SELECT * FROM sql_fullref WHERE sql_shortref.id > 0

    Changes in class Field

    • Field.sqlsafe now raises exception when the field object is not associated with any table.
    • Deprecated Field.sqlsafe_name, use Field._rname instead.
    • Added property Field.longname which returns field reference string as 'tablename.fieldname' (as oposed to 'table_rname.field_rname' returned by sqlsafe).
    • Field.clone() now returns the new Field object without link to any table and with empty _rname if it needs to be requoted.
    • Added method Field.bind() which links the field to a table. When the field is already linked, it raises exception. It also sets empty Field._rname to quoted Field.name. This method is called internally by table/subselect constructor.
    • Added Field._raw_rname which is the unquoted version of _rname.

    Other changes

    • Removed BaseAdatper.alias(), the code was move to Table.with_alias() where it belongs + bugfixes.
    • SQLDialect.update() and SQLDialect.delete() now take a Table object instead of tablename. This change was necessary because MySQLDialect.delete() and also other dialects need to access both sql_shortref and sql_fullref when the table is aliased.
    • New method writing_alias() added to SQLDialect. The method simply returns table.sql_fullref. It was added so that dialects like SQLite which don't support UPDATE/DELETE on aliased tables can raise exception without reimplementing the whole update()/delete() methods.
    • IMAP adapter was updated to new API (passing Table objects instead of tablename). I forgot to do this in the subselect pull request. Beware that this change is untested.
    • Field._rname and Field._raw_rname will now be stored in pickled table metadata files.
    opened by nextghost 25
  • [WIP] Indexes support

    [WIP] Indexes support

    Don't merge this until I say is ready

    This implements basic indexes support as requested in #152. Intended workflow:

    # just fields
    db.mytable.create_index('index_name', db.mytable.myfield_a, db.mytable.myfield_b)
    # with expressions
    db.mytable.create_index('index_name', db.mytable.myfield_a, db.mytable.myfield_b.coalesce(None))
    # with additional parameters (where is supported only by postgres)
    db.mytable.create_index('index_name', db.mytable.myfield_a, where=(db.mytable.myfield_b == False), unique=True)

    @niphlod @mdipierro @ilvalle @michele-comitini feedbacks are welcome.

    in progress 
    opened by gi0baro 20
  • sqlform.factory issue

    sqlform.factory issue

    It seems to me that sqlform factory is broken. Git bisect traced it down to commit @03dc3a8d4cddf3c1fd92cdab62d923d64f777776

    Traceback (most recent call last):
      File "/home/marin/web2py/gluon/restricted.py", line 227, in restricted
        exec ccode in environment
      File "/home/marin/web2py/applications/move/controllers/user.py", line 142, in <module>
      File "/home/marin/web2py/gluon/globals.py", line 412, in <lambda>
        self._caller = lambda f: f()
      File "/home/marin/web2py/applications/move/controllers/user.py", line 98, in login
        form = SQLFORM.factory(Field('email', 'string'), Field('password', 'string')).process(keepvalues=True)
      File "/home/marin/web2py/gluon/html.py", line 2301, in process
      File "/home/marin/web2py/gluon/html.py", line 2238, in validate
        if self.accepts(**kwargs):
      File "/home/marin/web2py/gluon/sqlhtml.py", line 1688, in accepts
        self.vars.id = self.table.insert(**fields)
      File "/home/marin/web2py/gluon/packages/dal/pydal/objects.py", line 706, in insert
        ret = self._db._adapter.insert(self, self._listify(fields))
      File "/home/marin/web2py/gluon/packages/dal/pydal/adapters/base.py", line 737, in insert
        raise e
    ValueError: INSERT INTO no_table(password,email) VALUES ('password','[email protected]');
    opened by mpranjic 19
  • Init adapters properly even when reusing idle connection from pool

    Init adapters properly even when reusing idle connection from pool

    Some adapters are not properly initialized when they reuse idle connection from pool. In case of PostgreSQL, this actually results in unnecessary migrations of json fields back and forth between TEXT and JSON SQL types because the adapter will not check whether it can use dialects with native JSON support.

    This pull request introduces new after_reconnect() adapter method which will be executed every time the connection is assigned to a new adapter object, no matter whether the connection was freshly created or reused from connection pool.

    opened by nextghost 18
  • Row.__getattr__ raises AttributeError when trying to access '_extra'

    Row.__getattr__ raises AttributeError when trying to access '_extra'

    Just spotted. I have this Row returned from pyDAL:

    <Row {'users': {'id': 26470719833643260735021266671L}, '_extra': {'registration_id': '', 'last_name': 'Barillari', 'first_name': 'Giovanni', 'reset_password_key': '', 'password': '***', 'registration_key': 'b40bde36-258a-48fb-b565-ec22cabc0586', 'email': '***'}}>

    In v15.03 was working as expected. In current master the problem seems caused by the difference behavior between Row.__getitem__ and Row.__getattr__. @ilvalle maybe a consequence of your refactoring with BasicStorage? I propose to add a:

    __getattr__ = __getitem__

    in Row class.

    opened by gi0baro 16
  • fix allowed table and field names

    fix allowed table and field names

    As discussed in web2py-developers (such as here ), we should avoid any table and field name that is not coherent with python identifiers. The cleanup() needs a revision and tests should be added to avoid regressions. We have rname for legacy and/or funny names.

    opened by niphlod 16
  • MSSQL adapter, tableX_view.insert (..) + trigger INSTEAD OF INSERT, .lastrowid (),

    MSSQL adapter, tableX_view.insert (..) + trigger INSTEAD OF INSERT, .lastrowid (), "SELECT SCOPE_IDENTITY ()", return long (../ None / ..)

    pseudo: CREATE TABLE tableX .. CREATE VIEW tableX_view CREATE TRIGGER tableX_view_trigger ON tableX_view INSTEAD OF INSERT AS .. IF a=b BEGIN INSERT INTO tableY FROM inserted .. END

    File "C:\python\Python37-32\lib\site-packages\pydal\adapters\mssql.py", line 98, in lastrowid return long(self.cursor.fetchone()[0]) TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'

    """ def lastrowid(self, table): self.execute("SELECT SCOPE_IDENTITY();") return long(self.cursor.fetchone()[0]) """ suggestions: 1/ self.execute("SELECT @@IDENTITY();") MSSQL Docs 2/ try: return long(self.cursor.fetchone()[0]) except (TypeError): return None

    opened by mari0sz 0
  • Only use TextIOWrapper if needed

    Only use TextIOWrapper if needed

    Fix the exception when TextIOWrapper is used twice. Happens if IO stream have to be converted before, for instance when CSV file are uploaded dynamically. See issue #671 for more details.

    opened by jvanbraekel 0
  • Fix unable to parse csv file in web2py break  CSV parsing when dynamic upload is used

    Fix unable to parse csv file in web2py break CSV parsing when dynamic upload is used


    The PR #654, actually break the CSV parsing, when it was working previously... Specifically, in case of dynamic upload in web2py : when the CSV file is uploaded trough the application before import into the database. TextIOWrapper is then already used to convert the binary stream into a string one the second usage in csv.reader raise an exception.

    An example of usage in web2py controller typically looks like this : db.import_from_csv_file(TextIOWrapper(request.vars.file_selector.file,encoding='utf8'))

    Removing TextIOWrapper from the call don't work, because pydal, 'object' and 'base' class are expecting string and not binary data. Consequently, all the parsing/format tests check for hard-coded string values ( for instance "TABLE' and not b"TABLE"), thus crash when binary data is used.

    opened by jvanbraekel 0
  • The 'fixed pickle raw' break db.tableName usage

    The 'fixed pickle raw' break db.tableName usage


    The 'fixed pickle raw' commit : b9277a41940f34cb43203e4b7285f157fa26b4df, break the db queries of type db(db.TableName.field == value) . While db(db.TableName.id == request.vars.id) is broken, the equivalent db.TableName(request.vars.id) is still fine trough. However there is not always an existing equivalent; for instance for select on non id fields or when the render() function is used afterwards.

    Following an example of errors I get :

    File "/opt/apps/web2py/gluon/restricted.py", line 219, in restricted exec(ccode, environment) File "/opt/apps/web2py/applications/.../controllers/controllername.py", line 206, in File "/opt/apps/web2py/gluon/globals.py", line 430, in self._caller = lambda f: f() File "/opt/apps/web2py/applications/.../controllers/default.py", line 159, in ... current_object = db(db.TableName.id == request.vars.id).select().render(0,fields=[db.TableName.field]) File "/opt/apps/web2py/gluon/packages/dal/pydal/objects.py", line 3571, in render row[field._tablename][field.name], File "/opt/apps/web2py/gluon/packages/dal/pydal/objects.py", line 146, in getitem raise KeyError(key) KeyError: 'TableName'

    The only solution I have at the moment is to roll back to the previous commit , namely : 7237a873d66e7798f88fcd19ec06304e3d19c70f

    opened by jvanbraekel 0
  • range_error_message raises TypeError when error_message is a translator

    range_error_message raises TypeError when error_message is a translator

    from pydal import validators
    from py4web import Translator
    # T = Translator("soccer/translations")
    # T.select("es")
    T = Translator()
    # default error message works fine
    r = validators.range_error_message(None, what_to_enter = "a number", minimum=1, maximum=8)
    # string works fine
    r = validators.range_error_message("Hello", what_to_enter = "a number", minimum=1, maximum=8)
    # use of translator fails
    # TypeError: unsupported operand type(s) for %: 'lazyT' and 'dict'
    r = validators.range_error_message(T("Hello"), what_to_enter = "a number", minimum=1, maximum=8)  

    I believe the code: return translate(error_message) % dict(min=minimum, max=maximum) should be replaced with return str(translate(error_message)) % dict(min=minimum, max=maximum)

    opened by anonymous378 0
  • blobs get truncated when read

    blobs get truncated when read

    Crhis from the py4web forum brought this up:

    Making more test when pydal retrieve the blob data from the db is only getting just a part of the information.

    When in print the rows after the select i get a small sample like this:

    images = cherry_db(cherry_db.image.node_id == i['node_id']).select(cherry_db.image.node_id, cherry_db.image.png)

    for m in images: print(m['png’])

    b'<\xd1\x88\x1c4l\x04\x84\xce 0\x13\xc6\x01\r\xdd\xd0'

    opened by Kkeller83 0
  • support for IN SQL statement

    support for IN SQL statement

    To be honest I was sure pydal has one. I cannot find it, so - i guess it's not in I miss the option to use IN statement in queries. For example

    SELECT `table`.`name` FROM `table` WHERE `id` IN ('1', '2', '3')

    I'd imaging the syntax going something like this:

    opened by guruyaya 1
  • global name 'urllib' is not defined in pyDAL==17.11

    global name 'urllib' is not defined in pyDAL==17.11

    if not decode_credentials:
        credential_decoder = lambda cred: cred
        credential_decoder = lambda cred: urllib.unquote(cred)

    This should be

    if not decode_credentials:
        credential_decoder = lambda cred: cred
        credential_decoder = lambda cred: unquote(cred)

    I know this will be fixed in next version, but currently my web2py application is using pyDAL 17.11, upgrade pyDAL to later version will cause my app behaves incorrectly (or crashes).

    opened by ngodinhnhien 0
  • table_class and fields

    table_class and fields

    class Account(Table):
        email = Field('email', type='string', unique=True)
        password = Field('password', type='password')
    db.define_table('account', table_class=Account)
    db.account.fields() # return ['id']

    Class table is only needed for their own methods? Or am I doing something wrong?

    opened by bronte2k7 2
  • async support

    async support

    tested pydal with blacksheep (add async on def function and await on db IO operation), but got an error exposed/install.py

    @app.route('/install', methods = ['GET'] )
    async def install(request):
        if db(db.test).isempty():
            test_id_1 = await db.test.insert(name = "test1")
            test_id_1 = await db.test.insert(name = "test2")
        return responses.redirect('/api/get/test/1')


    Internal Server Error.
    While handling request: GET /install
    Exception type:
    Exception message:
    object Reference can't be used in 'await' expression
    Stack trace:
    Traceback (most recent call last):
      File "blacksheep/baseapp.pyx", line 72, in blacksheep.baseapp.BaseApplication.handle
      File "/Users/sugizo/Downloads/blacksheep_pydal/test/exposed/install.py", line 10, in install
        test_id_1 = await db.test.insert(name = "test1")
    TypeError: object Reference can't be used in 'await' expression
    Process ID: 1885.


    @app.route('/api/get/{tablename}/{rec_id}', methods = ['GET'] )
    async def get(request, tablename, rec_id):
        query = (db[tablename]['id'] == rec_id)
        rows = await db(query).select().as_json()
        return responses.text(rows)


    Internal Server Error.
    While handling request: GET /api/get/test/1
    Exception type:
    Exception message:
    object str can't be used in 'await' expression
    Stack trace:
    Traceback (most recent call last):
      File "blacksheep/baseapp.pyx", line 72, in blacksheep.baseapp.BaseApplication.handle
      File "/Users/sugizo/miniconda3/envs/python3_test/lib/python3.8/site-packages/blacksheep/server/normalization.py", line 438, in handler
        return await method(*values)
      File "/Users/sugizo/Downloads/blacksheep_pydal/test/exposed/api.py", line 18, in get
        rows = await db(query).select().as_json()
    TypeError: object str can't be used in 'await' expression
    Process ID: 1916.

    seems pydal not support async at the moment it'll nice to have pydal support async


    opened by sugizo 0
  • v20200321.1(Mar 21, 2020)

  • v18.08(Aug 6, 2018)

  • v17.11(Nov 13, 2017)

  • v17.08(Aug 28, 2017)

  • v17.07(Jul 4, 2017)

    July 2017 release

    • Various bugfixes
    • Field.set_attributes now returns the instance
    • [PostgreSQL] Added jsonb type and serialization/parsing support
    • Added unix socket support in MySQL and PostgreSQL adapters
    • [GCP] Added MySQL and PostgreSQL support
    Source code(tar.gz)
    Source code(zip)
  • v17.03(Mar 9, 2017)

  • v17.01(Jan 31, 2017)

  • v16.11(Nov 10, 2016)

  • v16.09(Sep 28, 2016)

    September 2016 release

    • [MongoDB] Enabled query(field==list:reference)
    • [PostgreSQL] Several bugfixes
    • Improved portalocker behaviour on py3
    Source code(tar.gz)
    Source code(zip)
  • v16.08(Aug 13, 2016)

  • v16.07(Jul 25, 2016)

  • v16.06.28(Jun 28, 2016)

  • v16.06.20(Jun 20, 2016)

  • v16.06.09(Jun 9, 2016)

    Bugfix release

    Changes since 16.06:

    • Fixed boolean parsing errors on Postgre introduced with 16.06
    • Fixed connection issues on multiprocessing environments with pre-fork
    • Added 'postgres3' adapter to use driver 'boolean' type on fields
    Source code(tar.gz)
    Source code(zip)
  • v16.06(Jun 6, 2016)

    June 2016 release

    • Major refactoring of the codebase
    • Improved Postgre adapter performance
    • [MSSQL] Fixed sql generation with orderby on MSSQL3 adapters
    • Connection and cursors are now thread safe
    • [Mongo] Empty values for ObjectId fields are now stored and parsed as None instead of a fake ObjectId(0)
    • Fixed multiple calls of initialization callbacks during connection
    • [Postgre] Added more extraction helpers on fields
    • Enabled entity quoting as default behavior
    • Added indexes creation and drop support on SQL adapters
    • Several bugfixes
    Source code(tar.gz)
    Source code(zip)
  • v16.03(Mar 23, 2016)

    March 2016 Release

    • Implemented faster SQLite logic in absence of db queris
    • PEP8 improvements
    • Added support for new relic (newrelic>=
    • Added support for outerscoped tablenames
    • Fixed Google Cloud SQL support
    • Fixed Oracle DB support
    • Serveral bugfixes
    Source code(tar.gz)
    Source code(zip)
  • v15.12(Dec 16, 2015)

    December 2015 Release

    • Added IPV6 address enclosed in brackets support for URI's host
    • [MongoDB] Implemented unique and notnull support for fields during insert
    • Several bugfixes
    Source code(tar.gz)
    Source code(zip)
  • v15.09(Sep 28, 2015)

    2015 September release

    • [MongoDB] Implemented orderby_on_limitby
    • [MongoDB] Implemented distinct for count
    • [MongoDB] Implemented select() with having parameter
    • [MongoDB] Implemented coalesce operations
    • Virtual fields are now ordered depending on definition
    • Allow usage of custom Row classes
    • Added .where method to Set and DAL
    • Several bugfixes
    Source code(tar.gz)
    Source code(zip)
  • v15.07(Jul 10, 2015)

    2015 July release

    • Added smart_query support for 'contains' on fields of type 'list:string'
    • Implemented correct escaping for 'LIKE' (see https://github.com/web2py/pydal/issues/212)
    • Added support for ondelete with fields of type 'list:reference' on MongoDBAdapter
    • Improved BasicStorage performance
    • Added arithmetic expressions support on MongoDBAdapter
    • Added aggregations support on MongoDBAdapter
    • Table.validate_and_insert and Table.validate_and_update methods now validates also empty fields
    • Added support for expression operators on MongoDBAdapter
    • Several bugfixes
    Source code(tar.gz)
    Source code(zip)
  • v15.05.29(May 29, 2015)

  • v15.05.26(May 26, 2015)

  • v15.05(May 23, 2015)

    2015 May release

    • Fixed True/False expressions in MSSQL
    • Introduced iterselect() and IterRows
    • Extended SQLCustomType to support widget & represent attributes
    • Updated MongoDBAdapter to support pymongo 3.0
    • Implemented JSON serialization for objects
    • Refactored many internal objects to improve performance
    • Added python 3.x support (experimental)
    • Several fixes and improvements to MongoDBAdapter
    • Implemented unicode handling in MSSQL (experimental) via mssql4n and mssql3n adapters
      Notes: These adapters will probably become the de-facto standard for MSSQL handling; any other adapter will continue to be supported just for legacy databases
    • Restricted table and field names to "valid" ones
      Notes: the "dotted-notation-friendly" syntax for names means anything:
      - alphanumeric
      - not starting with underscore or an integer
      rname attribute is intended to be used for anything else
    Source code(tar.gz)
    Source code(zip)
  • v15.03(Mar 24, 2015)

    2015 March release

    • Fixed redefine with lazy tables
    • Added tests for update_or_insert, bulk_insert, validate_and_update_or_insert
    • Enhanced connections open/close flow
    • Enhanced logging flow
    • Refactored google adapters: ndb is now used by default
    • Added default representation for reference fields
    • Fixed some caching issues when using pickle
    • Several improvements and fixes in MongoDBAdapter
    Source code(tar.gz)
    Source code(zip)
  • v15.02.27(Feb 27, 2015)

  • v15.02(Feb 9, 2015)

    2015 February release

    • Updated pg8000 support in PostgreSQLAdapter
    • Fixed ilike for Field type 'list:string' in PostgreSQLAdapter
    • Added case sensitive/insensitive tests for contains
    • Fixed expression evaluation on PostgreSQLAdapter
    • Fixed common_filter issue in _enable_record_versioning
    • Removed contrib drivers
    • Fixed uuid attribute of DAL class
    • Added caching tests
    Source code(tar.gz)
    Source code(zip)
  • v0.12.25(Dec 25, 2014)

The Orator ORM provides a simple yet beautiful ActiveRecord implementation.

Orator The Orator ORM provides a simple yet beautiful ActiveRecord implementation. It is inspired by the database part of the Laravel framework, but l

Sébastien Eustace 1.3k Oct 17, 2021
A curated list of awesome tools for SQLAlchemy

Awesome SQLAlchemy A curated list of awesome extra libraries and resources for SQLAlchemy. Inspired by awesome-python. (See also other awesome lists!)

Hong Minhee (洪 民憙) 2.3k Oct 21, 2021
SQLModel is a library for interacting with SQL databases from Python code, with Python objects.

SQLModel is a library for interacting with SQL databases from Python code, with Python objects. It is designed to be intuitive, easy to use, highly compatible, and robust.

Sebastián Ramírez 5.5k Oct 24, 2021
An async ORM. 🗃

ORM The orm package is an async ORM for Python, with support for Postgres, MySQL, and SQLite. ORM is built with: SQLAlchemy core for query building. d

Encode 1.4k Oct 11, 2021
Pony Object Relational Mapper

Downloads Pony Object-Relational Mapper Pony is an advanced object-relational mapper. The most interesting feature of Pony is its ability to write que

null 2.7k Oct 25, 2021
Tortoise ORM is an easy-to-use asyncio ORM inspired by Django.

Tortoise ORM was build with relations in mind and admiration for the excellent and popular Django ORM. It's engraved in it's design that you are working not with just tables, you work with relational data.

Tortoise 2.4k Oct 20, 2021
Beanie - is an Asynchronous Python object-document mapper (ODM) for MongoDB

Beanie - is an Asynchronous Python object-document mapper (ODM) for MongoDB, based on Motor and Pydantic.

Roman 277 Oct 18, 2021
Piccolo - A fast, user friendly ORM and query builder which supports asyncio.

A fast, user friendly ORM and query builder which supports asyncio.

null 566 Oct 20, 2021
a small, expressive orm -- supports postgresql, mysql and sqlite

peewee Peewee is a simple and small ORM. It has few (but expressive) concepts, making it easy to learn and intuitive to use. a small, expressive ORM p

Charles Leifer 8.7k Oct 25, 2021
A very simple CRUD class for SQLModel! ✨

Base SQLModel A very simple CRUD class for SQLModel! ✨ Inspired on: Full Stack FastAPI and PostgreSQL - Base Project Generator FastAPI Microservices I

Marcelo Trylesinski 12 Oct 22, 2021
A Python Object-Document-Mapper for working with MongoDB

MongoEngine Info: MongoEngine is an ORM-like layer on top of PyMongo. Repository: https://github.com/MongoEngine/mongoengine Author: Harry Marr (http:

MongoEngine 3.6k Oct 24, 2021
Easy-to-use data handling for SQL data stores with support for implicit table creation, bulk loading, and transactions.

dataset: databases for lazy people In short, dataset makes reading and writing data in databases as simple as reading and writing JSON files. Read the

Friedrich Lindenberg 4.1k Oct 18, 2021
A pythonic interface to Amazon's DynamoDB

PynamoDB A Pythonic interface for Amazon's DynamoDB. DynamoDB is a great NoSQL service provided by Amazon, but the API is verbose. PynamoDB presents y

null 1.7k Oct 23, 2021
Rich Python data types for Redis

Created by Stephen McDonald Introduction HOT Redis is a wrapper library for the redis-py client. Rather than calling the Redis commands directly from

Stephen McDonald 273 Sep 2, 2021
A Python Library for Simple Models and Containers Persisted in Redis

Redisco Python Containers and Simple Models for Redis Description Redisco allows you to store objects in Redis. It is inspired by the Ruby library Ohm

sebastien requiem 434 Oct 1, 2021
Pydantic model support for Django ORM

Pydantic model support for Django ORM

Jordan Eremieff 189 Oct 23, 2021
MongoEngine flask extension with WTF model forms support

Flask-MongoEngine Info: MongoEngine for Flask web applications. Repository: https://github.com/MongoEngine/flask-mongoengine About Flask-MongoEngine i

MongoEngine 788 Oct 14, 2021
Adds SQLAlchemy support to Flask

Flask-SQLAlchemy Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application. It aims to simplify using SQLAlchemy

The Pallets Projects 3.6k Oct 22, 2021