Skip to main content

Use Python with or without an ORM.

Project description

Use Python with or without an ORM.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

PyNoORM consists of several very loosely-coupled classes that facilitate the use of Python in a web or SQL
context without having to rely on an ORM. Working with an ORM is entirely possible, in fact, it's used with
the Django ORM and SQLAlchemy in an application that interfaces with Oracle, Microsoft SQL Server and PostgreSQL all at the same time.

Focus is on:

- simplicity for the user
- support for databases that are not under "controlled" by the Python application or may be read-only for it.
- performance

+------------------------+-----------------------------------------------------------------------+
| Class | Role |
+========================+=======================================================================+
| Binder | abstract SQL query binding |
+------------------------+-----------------------------------------------------------------------+
| Linker | join objects together |
+------------------------+-----------------------------------------------------------------------+
| TemplateGenerator | generate Django Templates dynamically from query results, loosely |
| *(to be added)* | inspired by Django Tables 2 |
+------------------------+-----------------------------------------------------------------------+


The Binder class
================

A Binder support easier raw SQL by abstracting differences in the underlying database's bind variable syntax and also substituting bind variables from a list of arguments, using dict, then attribute lookup.

Using native database binds also helps to protect you against SQL injection attacks.

supported: PostgreSQL, sqlite3, Oracle, MySQL, SQL Server

Basic Use
---------

Simple **sqlite3** example::

from pynoorm.binder import Binder
binder = Binder.factory("qmark")

query, parameters = binder("select * from orders where custid = %(custid)s", dict(custid="ACME"), binder)

``query`` and ``parameters`` are now in the sqlite3/qmark format::

>>> print(query)
select * from orders where custid = ?
>>> print(parameters)
('ACME',)

Oracle, with mutiple parameters ::

import cx_Oracle
binder_ora = Binder.factory(cx_Oracle.paramstyle)

#just for test... assign a custid for attribute lookup
binder_ora.custid = "AMAZON"

tqry = "select * from orders where custid = %(custid)s and has_shipped = %(shipped)s"
query, parameters = binder_ora(tqry, binder_ora, dict(custid="ACME", shipped=1))

>>> print(query)
select * from orders where custid = :custid and has_shipped = :shipped
>>> print(parameters)
{'shipped': 1, 'custid': 'AMAZON'}



Features
--------

* adjust query to support database parameter style
* find and prepare bind parameters from `*args`.



The Linker class
============

A Linker allows you to join objects or dictionaries without the need for an ORM. You can think of it as performing `parent-child` linking, but it uses `left-right` instead as a more neutral terminology instead.

Basic use
---------

Sample data, in dictionaries: ::

customers = [
dict(id=1, xref=1),
dict(id=2, xref=2),
]

orders = [
dict(custid=1, xref=1, orderid=11),
dict(custid=1, xref=1, orderid=12),
dict(custid=2, xref=2, orderid=21),
dict(custid=2, xref=2, orderid=22),
]

Create a linker, then a lookup dictionary for the left side. Finally, link the left and right side. ::

linker = Linker(key_left="id")
lookup = linker.dict_from_list(customers)
linker.link(lookup, orders, attrname_on_left="orders", key_right="custid")


The customers now have an `orders` list: ::

[ { 'id': 1,
'orders': [ { 'custid': 1, 'orderid': 11, 'xref': 1},
{ 'custid': 1, 'orderid': 12, 'xref': 1}],
'xref': 1},
{ 'id': 2,
'orders': [ { 'custid': 2, 'orderid': 21, 'xref': 2},
{ 'custid': 2, 'orderid': 22, 'xref': 2}],
'xref': 2}]

Features
--------

* supports objects or dictionaries
* takes basic Python objects so can join across different databases, allowing for example tagging of objects in a read-only database
* allows compound field keys and aliasing
* orphans, on the left or the right, can be initialized with empty attribute values.


Credits
---------

This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.

.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage


=======
History
=======

0.1.0 (2016-02-17)
------------------

* First release on github.

0.1.1 (2016-02-22)
------------------

* Registered on PyPI

0.2.0 (2016-04-12)
------------------

* Added support for Python 3.3+ and MySQL

0.3.0 (2017-09-06)
------------------

* Added SQL Server support
* Added Linker class to support object cross-referencing

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pynoorm-0.3.0.tar.gz (38.2 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page