{ "info": { "author": "Tommy MacWilliam", "author_email": "tmacwilliam@cs.harvard.edu", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3 :: Only", "Topic :: Database" ], "description": "Stellata\n========\n\nStellata is a simple PostgreSQL ORM for Python 3.\n\nConnecting\n----------\n\nTo connect to a database on the default host/port with a threaded\nconnection pool of size 10:\n\n::\n\n import stellata.database\n\n db = stellata.database.initialize(\n name='database',\n user='user',\n password='password',\n host='localhost',\n port=5432,\n pool_size=10\n )\n\nDefining Models\n---------------\n\nA user model might look something like this:\n\n::\n\n import stellata.fields\n import stellata.model\n\n class User(stellata.model.Model):\n __table__ = 'users'\n\n id = stellata.fields.UUID(null=False)\n active = stellata.fields.Integer(default=1)\n name = stellata.fields.Text(null=False)\n hash = stellata.fields.Varchar(length=255)\n email = stellata.fields.Text()\n dt = stellata.fields.Timestamp(null=False)\n\nThe ``__table__`` property is the name of the corresponding table in the\nPostgreSQL database. Each property corresponds to a column, and the\nclasses in ``stellata.fields`` are used to define the column types.\n\nField Types\n~~~~~~~~~~~\n\n- BigInteger\n- Boolean\n- Integer\n- Numeric\n- Text\n- Timestamp\n- UUID\n- Varchar\n\nRelations\n~~~~~~~~~\n\nLike any good ORM, Stellata supports relations among models. Here are\ntwo related models, ``A`` and ``B``:\n\n::\n\n import stellata.model\n import stellata.fields\n import stellata.relations\n\n class A(stellata.model.Model):\n __table__ = 'a'\n\n id = stellata.fields.UUID()\n foo = stellata.fields.Text()\n bar = stellata.fields.Integer(default=0, null=False)\n\n b = stellata.relations.HasMany(lambda: B.a_id)\n\n class B(stellata.model.Model):\n __table__ = 'b'\n\n id = stellata.fields.UUID()\n a_id = stellata.fields.UUID()\n bar = stellata.fields.Integer(null=False)\n\n a = stellata.relations.BelongsTo(lambda: B.a_id, lambda: A)\n\nIndexes\n~~~~~~~\n\nIndexes make your queries go fast. Let's add a couple indexes to our\ntable:\n\n::\n\n import stellata.model\n import stellata.fields\n import stellata.index\n import stellata.relations\n\n class A(stellata.model.Model):\n __table__ = 'a'\n\n id = stellata.fields.UUID()\n foo = stellata.fields.Text()\n bar = stellata.fields.Integer(default=0, null=False)\n\n b = stellata.relations.HasMany(lambda: B.A_id, lambda: A)\n\n primary_key = stellata.index.PrimaryKey(lambda: A.id)\n foo_index = stellata.index.Index(lambda: A.foo, unique=True)\n\nSerialization\n~~~~~~~~~~~~~\n\nOnce you have some data, it won't be long until you want to convert it\nto JSON. To do so, use:\n\n::\n\n stellata.model.serialize(model)\n\nThis will recursively serialize objects/relations, and you can pass it\nan object, dictionary, list, etc.\n\nMeta\n~~~~\n\nIn some cases, it's handy to be able to iterate over all of the models\nyou've defined. For example, you might want to truncate tables for a\nunit test. In that case, you can do this:\n\n::\n\n for model in stellata.model.registered():\n # do something with model\n\nMigration\n---------\n\nOnce you've defined your models, you can sync them with your database by\nperforming a migration.\n\n::\n\n stellata.schema.migrate(db, execute=True)\n\nHere, ``db`` is the handle returned by the\n``stellata.database.initialize`` call. If you'd like to do a dry run,\nwithout actually executing any queries, do:\n\n::\n\n stellata.schema.migrate(db)\n\nIn both cases, this function will return a list of queries needed for\nthe migration.\n\nResetting\n~~~~~~~~~\n\nIn some development scripts, you might want to clean your database. If\nyou so desire, you can do this:\n\n::\n\n stellata.schema.drop_tables_and_lose_all_data(db, execute=True)\n\nAs its name suggests, this function is very destructive, so don't do\nthis on a production database.\n\nCRUD Operations\n---------------\n\nFinally, let's walk through how to use Stellata to query your database.\n\nCreate\n~~~~~~\n\nLet's create a new instance of ``A``.\n\n::\n\n a = A.create(A(foo='bar', bar=5))\n a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n a.foo == 'bar'\n a.bar == 4\n\nOr, if we want to create in bulk:\n\n::\n\n result = A.create([\n A(foo='bar', bar=6),\n A(foo='baz', bar=7)\n ])\n\n len(result) == 2\n\nIf you created a unique index on some fields, you can take advantage of\nthe PostgreSQL ON CONFLICT feature:\n\n::\n\n A.create(A(foo='baz', bar=9), unique=(A.foo,))\n\nNow, if there's already a row with ``foo`` having a value of ``baz``,\nthen the ``bar`` column will be updated to have a value of ``9``, rather\nthan creating a new row.\n\nRead\n~~~~\n\nTo read from the database, we'll want to use the ``where`` method. Let's\nget the instance of ``A`` we created before:\n\n::\n\n a = A.where(A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca').get()\n a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n\nJeez Rick, what's that syntax? We're using operator overloading, Morty.\nWhat else can we do?\n\n::\n\n A.where(A.bar < 5).get()\n A.where(A.bar > 1).get()\n A.where(A.id << ['2a12f545-c587-4b99-8fd2-57e79f7c8bca', '31be0c81-f5ee-49b9-a624-356402427f76']).get()\n\nThat last one is a where in query, in case that wasn't\u2014burp\u2014obvious. We\ncan also use AND and OR in our queries like so:\n\n::\n\n A.where((A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca') | (A.bar < 5)).get()\n A.where((A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca') & (A.bar > 1)).get()\n\nOther bells and whistles:\n\n::\n\n A.where(A.bar < 5).order(A.bar, 'asc').limit(5).get()\n\nA common read operation is to find all rows where a column matches some\nvalue, so we can use a shorthand:\n\n::\n\n A.find('2a12f545-c587-4b99-8fd2-57e79f7c8bca')\n\nBy default, the ``id`` field will be used, but you can also specify your\nown field:\n\n::\n\n A.find(5, A.bar)\n\nIf given a list, ``find`` will return a dictionary keyed on the value of\nthe field you specify:\n\n::\n\n a = A.find(['2a12f545-c587-4b99-8fd2-57e79f7c8bca', '31be0c81-f5ee-49b9-a624-356402427f76'])\n a['2a12f545-c587-4b99-8fd2-57e79f7c8bca'].id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n a['31be0c81-f5ee-49b9-a624-356402427f76'].id == '31be0c81-f5ee-49b9-a624-356402427f76'\n\nJoins\n~~~~~\n\nWe can use those relations we set up earlier with joins. Let's say we\ncreate the following:\n\n::\n\n a = A.create(A(foo='bar', bar=5))\n a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n b = B.create([\n B(a_id='2a12f545-c587-4b99-8fd2-57e79f7c8bca', qux=3)\n B(a_id='2a12f545-c587-4b99-8fd2-57e79f7c8bca', qux=5)\n ])\n\nNow, we can do this:\n\n::\n\n a = A.join(A.b).where(A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca').get()\n a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n len(a.b) == 2\n a.b[0].qux == 3\n a.b[1].qux == 5\n\nOr, the other way:\n\n::\n\n b = B.join(B.a).where(B.qux << [3, 5]).get()\n len(b) == 2\n b[0].qux == 3\n b[0].a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n b[1].qux == 5\n b[1].a.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca'\n\nBy default, joins will be executed via multiple SELECT queries. If you'd\nprefer to do a JOIN instead, just do this:\n\n::\n\n a = A.join_with('join').join(A.b).where(A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca').get()\n\nThe result is the same as before, but the underlying query was\ndifferent. Which method you use is entirely up to you, and may vary with\ndifferent queries.\n\nUpdate\n~~~~~~\n\nAs you might expect, update queries combine the syntax for creating and\nreading:\n\n::\n\n A.where(A.id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca').update(A(bar=7))\n\nDelete\n~~~~~~\n\nThis one is easy now.\n\n::\n\n A.where(id == '2a12f545-c587-4b99-8fd2-57e79f7c8bca').delete()\n\nOr, if you prefer a single TRUNCATE operation:\n\n::\n\n A.truncate()\n\nTransactions\n~~~~~~~~~~~~\n\nStellata also has support for PostgreSQL transactions:\n\n::\n\n A.begin()\n A.truncate()\n A.create([A(bar=1), A(bar=2)])\n A.commit()", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/tmacwill/stellata", "keywords": "orm postgres postgresql", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "stellata", "package_url": "https://pypi.org/project/stellata/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/stellata/", "project_urls": { "Homepage": "https://github.com/tmacwill/stellata" }, "release_url": "https://pypi.org/project/stellata/0.0.2/", "requires_dist": [ "psycopg2" ], "requires_python": "", "summary": "A simple ORM for PostgreSQL.", "version": "0.0.2" }, "last_serial": 2863648, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "0a09c280dd04c5f73476d9b9a256d944", "sha256": "1abc0f81e3eb063c00b3e211a8b483fee3eb1b6b806b568b37b5e28157056107" }, "downloads": -1, "filename": "stellata-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "0a09c280dd04c5f73476d9b9a256d944", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 24191, "upload_time": "2017-04-24T03:13:10", "url": "https://files.pythonhosted.org/packages/39/4f/4e323e58a40620b28b75a5a8b1e28dc859844265cf40cda9dd423d4a6c71/stellata-0.0.1-py3-none-any.whl" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "5211f6e05f6d0b97cb84c159a4bb5b53", "sha256": "63d8fdcd7f941c04b8232e8bafdd760f8d8dd67863c6b13c0ab1b8e30affc4ef" }, "downloads": -1, "filename": "stellata-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "5211f6e05f6d0b97cb84c159a4bb5b53", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 26284, "upload_time": "2017-05-10T07:44:39", "url": "https://files.pythonhosted.org/packages/66/40/f493407ff86297a914cabd817c6085bb18e2789633b6aca4d1cee778e394/stellata-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e88537fb4acf02f53585bad56eba4784", "sha256": "dfc13bd58fbbb9d1fd5107e0a49a8309e2197422dad8a0b4fba6065f204ffcd2" }, "downloads": -1, "filename": "stellata-0.0.2.tar.gz", "has_sig": false, "md5_digest": "e88537fb4acf02f53585bad56eba4784", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19094, "upload_time": "2017-05-10T07:44:41", "url": "https://files.pythonhosted.org/packages/d4/d7/a981a35b4cb82cc10c4f9960e1ba1091cb05edc23964a2900a5dead0b229/stellata-0.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5211f6e05f6d0b97cb84c159a4bb5b53", "sha256": "63d8fdcd7f941c04b8232e8bafdd760f8d8dd67863c6b13c0ab1b8e30affc4ef" }, "downloads": -1, "filename": "stellata-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "5211f6e05f6d0b97cb84c159a4bb5b53", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 26284, "upload_time": "2017-05-10T07:44:39", "url": "https://files.pythonhosted.org/packages/66/40/f493407ff86297a914cabd817c6085bb18e2789633b6aca4d1cee778e394/stellata-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e88537fb4acf02f53585bad56eba4784", "sha256": "dfc13bd58fbbb9d1fd5107e0a49a8309e2197422dad8a0b4fba6065f204ffcd2" }, "downloads": -1, "filename": "stellata-0.0.2.tar.gz", "has_sig": false, "md5_digest": "e88537fb4acf02f53585bad56eba4784", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 19094, "upload_time": "2017-05-10T07:44:41", "url": "https://files.pythonhosted.org/packages/d4/d7/a981a35b4cb82cc10c4f9960e1ba1091cb05edc23964a2900a5dead0b229/stellata-0.0.2.tar.gz" } ] }