{ "info": { "author": "Osvaldo Santana Neto", "author_email": "osantana@triveos.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Utilities" ], "description": "Django-ZODB\n===========\n\n`Django-ZODB`_ is a simple `ZODB`_ database backend for `Django`_ Framework.\nIt's strongly inpired in `repoze.zodbconn`_.\n\nInstallation\n------------\n\nDjango-ZODB requires the following packages:\n\n* `Django`_ 1.2.3 or newer\n* `ZODB`_ 3.10.0a2 or newer\n\nIf you need to store your data in a RDBMS system you will need to install the\nfollowing packages too:\n\n* `RelStorage`_ 1.5.0a1 or newer - ZODB storage system that store pickles in a\n relational database (in a non-relational format).\n* `MySQLdb`_ 1.2.3 or newer - required to connect `MySQL`_ database.\n* `psycopg2`_ 2.3.0-beta1 or newer - required to connect `PostgreSQL`_ database.\n* `cx_Oracle`_ 5.0.3 or newer - required to connect `Oracle`_ database.\n\n.. Note:: Not tested with ``psycopg2`` and ``cx_Oracle`` but we believe that\n everything will work as expected because we use ``RelStorage`` to connect to\n the database.\n\nInstall from sources::\n\n $ python setup.py install\n\nOr from PyPI (using easy_install)::\n\n $ easy_install -U django-zodb\n\nRunning tests\n-------------\n\nInstall coverage_ if you need test coverage informations::\n\n $ easy_install -U coverage\n\nTo run tests::\n\n $ python manage.py test\n\nConfiguration\n-------------\n\nYou need to configure your ``settings.py`` like this::\n\n ZODB = {\n 'default': [\n 'mysql://user@passwd:localhost/relstorage_db?database_name=app',\n 'postgresql://user@passwd:pg_test:5678/app1_db',\n ],\n 'test': [ 'mem://', 'mem://?database_name=catalog' ],\n 'legacy_db': [ 'zconfig:///srv/www/zodb_media.conf' ],\n 'user_dir': [\n 'zeo://main_db.intranet:7899?database_name=main',\n 'zeo://catalog.intranet:7898?database_name=catalog'\n ],\n 'old_app': [\n 'file:///var/lib/sitedata.db?blob_dir=/var/lib/blob_dir'\n ],\n }\n\nYou can find a list of schemes and connection adapters in `Connection Schemes`_.\n\nCreating sample application\n===========================\n\nI strongly believe in \"learn by doing\" strategy, so, let's create a sample\nWiki application that stores their pages in ZODB.\n\nI suggest the reading of the following tutorials and articles if you don't know\nZODB or the Traversal Algorithm (that we will use in our tutorial):\n\n* `ZODB Tutorial`_\n* `ZODB Programming Guide`_\n* `Traversal`_ chapter at `Repoze.BFG documentation`_.\n\n.. Note:: Repoze.BFG is now known as `Pyramid`_.\n\nStarting Django Project and Application\n---------------------------------------\n\nWe will start a project called ``intranet`` with a Django application called\n``wiki``::\n\n $ django-admin.py startproject intranet\n $ cd intranet\n intranet $ python manage.py startapp wiki\n\nNow we need to modify our ``settings.py`` to include this new application and\nconfigure our database connections::\n\n #!/usr/bin/env python\n # settings.py\n\n import os\n ROOTDIR = os.path.dirname(os.path.realpath(__file__))\n\n # No relational database...\n DATABASE_ENGINE = 'sqlite3'\n DATABASE_NAME = ':memory:'\n\n # append the following lines:\n ZODB = {\n 'default': ['file://' + os.path.join(ROOTDIR, 'wiki_db.fs')],\n }\n\n # ... other Django configurations ...\n\n MIDDLEWARE_CLASSES = (\n # ... other middlewares ...\n\n # If everything is ok (aka no exception raised) this middleware will\n # run a transaction.commit() on response.\n 'django_zodb.middleware.TransactionMiddleware',\n )\n\n INSTALLED_APPS = (\n 'django_zodb', # enable manage.py zshell command\n 'wiki',\n )\n\nLet's create our model classes. We will need a \"root\" object that will store our\nobjects (let's name it ``Wiki``) and a model to store the wiki pages itself\n(``Page``)::\n\n #!/usr/bin/env python\n # wiki/models.py\n\n import markdown # http://pypi.python.org/pypi/Markdown\n from django_zodb import models\n\n # models.RootContainer - Define a 'root' object for database. This class\n # defines __parent__ = __name__ = None\n class Wiki(models.RootContainer):\n def pages(self):\n for pagename in sorted(self):\n yield self[pagename]\n\n def get_absolute_url(self):\n return \"/wiki\"\n\n # It's possible to change models.RootContainer settings using Meta\n # configurations. Here we will explicitly define the default values\n class Meta:\n database = 'default' # Optional. Default: 'default'\n rootname = 'wiki' # Optional. Default: RootClass.__name__.lower()\n\n # models.Container - We will use Container to add support to subpages.\n class Page(models.Model):\n def __init__(self, content=\"Empty Page.\"):\n super(Page, self).__init__()\n self.content = content\n\n def html(self):\n md = markdown.Markdown(safe_mode=\"escape\",\n extensions=('codehilite', 'def_list', 'fenced_code'))\n return md.convert(self.content)\n\n @property\n def name(self):\n return self.__name__\n\n def get_absolute_url(self):\n return u\"/\".join((self.__parent__.get_absolute_url(), self.name))\n\nWe've a configured application and models. It's time to map an URL to our view\nfunction::\n\n #!/usr/bin/env python\n # urls.py\n\n # ... Django default URL configurations ...\n\n urlpatterns = patterns('',\n # ... other URL mappings ...\n (r'^(?P.*)/?$', 'wiki.views.page'),\n )\n\nAnd ``wiki/views.py``::\n\n #!/usr/bin/env python\n # views.py\n\n import re\n\n from django.shortcuts import render_to_response\n from django.http import HttpResponseRedirect\n from django import forms\n\n import transaction\n from django_zodb import views\n from django_zodb import models\n\n from samples.wiki.models import Wiki, Page\n\n wikiwords = re.compile(ur\"\\b([A-Z]\\w+([A-Z]+\\w+)+)\")\n\n\n class PageEditForm(forms.Form):\n content = forms.CharField(widget=forms.Textarea)\n\n\n class WikiView(views.View):\n def __index__(self, request, context, root, subpath, traversed):\n return HttpResponseRedirect(\"FrontPage\")\n\n def add(self, request, context, root, subpath, traversed):\n try:\n name = subpath[0]\n except IndexError:\n return HttpResponseRedirect(\"/\")\n\n if request.method == \"POST\":\n form = PageEditForm(request.POST)\n if form.is_valid():\n page = Page(form.cleaned_data['content'])\n root[name] = page\n return HttpResponseRedirect(page.get_absolute_url())\n else:\n form = PageEditForm()\n\n page_data = {\n 'name': name,\n 'cancel_link': \"javascript:history.go(-1)\",\n 'form': form,\n }\n return render_to_response(\"edit.html\", page_data)\n views.registry.register(model=Wiki, view=WikiView())\n\n\n class PageView(views.View):\n def __index__(self, request, context, root, subpath, traversed):\n content = context.html()\n\n def check(match):\n word = match.group(1)\n if word in root:\n page = root[word]\n view_url = page.get_absolute_url()\n return '%s' % (view_url, word)\n else:\n add_url = models.model_path(root, \"\", \"add\", word)\n return '%s' % (add_url, word)\n\n content = wikiwords.sub(check, content)\n\n page_data = {\n 'context': context,\n 'content': content,\n 'edit_link': context.get_absolute_url() + \"/edit\",\n 'root': root,\n }\n return render_to_response(\"page.html\", page_data)\n\n def edit(self, request, context, root, subpath, traversed):\n context_path = models.model_path(context)\n\n if request.method == \"POST\":\n form = PageEditForm(request.POST)\n if form.is_valid():\n context.content = form.cleaned_data['content']\n return HttpResponseRedirect(context_path)\n else:\n form = PageEditForm(initial={'content': context.content})\n\n page_data = {\n 'name': context.name,\n 'context': context,\n 'cancel_link': context_path,\n 'form': form,\n }\n return render_to_response(\"edit.html\", page_data)\n views.registry.register(model=Page, view=PageView())\n\n\n def create_frontpage(root):\n frontpage = Page()\n root[\"FrontPage\"] = frontpage\n return root\n\n def page(request, path):\n root = models.get_root(Wiki, setup=create_frontpage)\n return views.get_response_or_404(request, root=root, path=path)\n\n\nTraversal\n---------\n\nFrom `Repoze.BFG documentation`_:\n\n Traversal is a context finding mechanism. It is the act of finding a context\n and a view name by walking over an object graph, starting from a root\n object, using a request object as a source of path information.\n\nDjango-ZODB implements the traversal algorithm in function\n``django_zodb.views.traverse()`` that receive two arguments:\n\n* ``root`` - an instance of Root model.\n* ``path`` - a string with the path to be traversed.\n\nAnd return a ``views.TraverseResult`` object with the following attributes:\n\n* ``context`` - model object found by traversal.\n* ``method_name`` - a method name if exists.\n* ``subpath`` - aditional path arguments.\n* ``traversed`` - path elements 'traversed'.\n* ``root`` - root object.\n\nWe've created some shortcuts functions to interpret these results:\n\n* ``get_response(request, root, path) -> HttpResponse``\n* ``get_response_or_404(request, root, path) -> HttpResponse or Http404``\n\nThese functions will traverse the model tree and call a registered view function\nthat handle the context model object found. For example::\n\n def handle_page_objects(request, result):\n # result is a TraverseResult object.\n # result.context is a Page object found by traverse\n return render_to_response(...)\n\n # Register handle_page_objects function to handle Page objects:\n views.registry.register(model=Page, view=handle_page_objects)\n\nYou can register a ``views.View()`` instance to handle model objects::\n\n class PageView(views.View):\n # This is the 'default' handle (no method_name)\n def __index__(self, request, context, root, subpath, traversed):\n # ... context is a Page object ...\n return render_to_response(...)\n\n # called when method_name == \"edit\"\n def edit(self, request, context, root, subpath, traversed):\n # ... context is a Page object ...\n return render_to_response(...)\n\n # Register a PageView *instance* to handle Page objects\n views.registry.register(model=Page, view=PageView())\n\n\n.. Connection Schemes:\n\nConnection Schemes\n------------------\n\nYou can specify a ZODB connection using a URI. This URI is composed of the\nfollowing arguments::\n\n scheme://username:password@host:port/path?arg1=foo&arg2=bar#fraction\n\nDepending on the chosen scheme some of these arguments are required and\nothers optional.\n\nDatabase and Connection settings\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nArguments related to database connection settings. These arguments are optional\nand must be passed as query argument in URI (eg. ``?database_name=db&...``).\n\n* ``database_name`` - ``str`` - database name used by ZODB.\n* ``connection_cache_size`` - ``int`` - size (in bytes) of database cache.\n* ``connection_pool_size`` - ``int`` - size of connection pool.\n\nThese arguments are passed to ``ZODB.DB.DB()`` constructor.\n\nMemory Storage ``mem:`` (``ZODB.MappingStorage``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns an in-memory storage. It's basically a Python ``dict()`` object.\n\nValid URIs::\n\n mem\n mem:\n mem://\n mem?database_name=memory\n\nOptional Arguments\n''''''''''''''''''\n\n* See `Demo storage argument`_.\n* See `Blob storage arguments`_.\n\nFile Storage ``file:`` (``ZODB.FileStorage``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns a database stored in a file. You need to specify an absolute path to the\ndatabase file.\n\nValid URIs::\n\n file:///tmp/Data.fs\n file:///tmp/main.db?database_name=file\n\nInvalid URIs::\n\n file://subdir/Data.fs\n\nRequired Arguments\n''''''''''''''''''\n\n* ``path`` - ``str`` - absolute path to file where database will be stored.\n\nOptional Arguments\n''''''''''''''''''\n\n* ``create`` - ``bool`` - create database file if does not exist. Default:\n ``create=True``.\n* ``read_only`` - ``bool`` - open storage only for reading. Default:\n ``read_only=False``.\n* ``quota`` - ``int`` - storage quota. Default: disabled (``quota=None``).\n* See `Demo storage argument`_.\n* See `Blob storage arguments`_.\n\n``zconfig:`` (``ZODB.DB.DB``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns database (or databases) specified in ZCML configuration file.\n\n.. Note:: This scheme has some small differences with other schemes because it\n returns a DB object instead of a Storage. It's a problem only in cases where\n you are creating the connection 'by hand' instead of use a higher level API.\n\nURIs Examples::\n\n zconfig:///my/app/zodb_config.zcml\n zconfig:///my/app/zodb_config.zcml#main\n\nRequired Arguments\n''''''''''''''''''\n\n* ``path`` (``str``) - absolute path to file where database will be stored.\n\nOptional Arguments (and default values)\n'''''''''''''''''''''''''''''''''''''''\n\n* ``#fragment=''`` (``str``) - Get only an specific database. By default\n (``''``) get only the first database specified in configuration file. We\n don't use a query argument (``&arg=...``) to specify database name to\n keep compatibility with `repoze.zodbconn`_.\n\n``zeo:`` (``ZEO.ClientStorage.ClientStorage``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns a connection to a ZEO server.\n\nTODO\n\n\n``mysql:`` (``RelStorage``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns a database stored in a MySQL relational server. This scheme uses\n`RelStorage`_ to establish connection with database server.\n\nURIs Examples::\n\n mysql://user:password@host:3306?compress=true#mysql_db_name\n mysql:///tmp/mysql.sock#local_database\n mysql://localhost#database\n\nArguments\n'''''''''\n\n* See `Relational storage arguments`_.\n\n``postgresql`` (``RelStorage``)\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nReturns a database stored in a PostgreSQL relational server. This scheme uses\n`RelStorage`_ to establish connection with database server.\n\nURIs Examples::\n\n postgresql://user:password@host:5432#mysql_db_name\n\nArguments\n'''''''''\n\n* See `Relational storage arguments`_.\n\n.. _`Demo storage argument`:\n\nDemo storage argument\n~~~~~~~~~~~~~~~~~~~~~\n\n* ``demostorage`` (``bool``) - Enable the ZODB's demo storage wrapper.\n\n.. _`Blob storage arguments`:\n\nBlob storage arguments\n~~~~~~~~~~~~~~~~~~~~~~\n\n* ``blob_dir`` (``str``) - Directory where blob objects will be stored.\n\n.. _`Relational storage arguments`:\n\nRelational storage arguments\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nDjango-ZODB uses `Relstorage`_ to connect to RDBMS and we preserve the same\narguments used by RelStorage. The only difference between RelStorage`s arguments and Django-ZODB arguments is that we use \"``_``\" (underline) instead of \"``-``\" (dash). For example: the RelStorage's argument \"``shared-blob-dir``\" becomes \"``shared_blob_dir``\".\n\nContributing\n------------\n\nHi, I'm accepting all kind of collaborations to this project. You can open issues in our issue tracker, send me a patch, an e-mail message with your questions, etc.\n\nAll kind of collaboration will be welcome.\n\nTODO\n----\n\n* Review my 'engrish' in documentation\n* Create a new Website\n* Release 0.2 version (and announce)\n* Test Relstorage connections with Oracle and PostgreSQL\n* Create more manage.py commands for ZODB management\n* Create a Django-ORM layer (wow!)\n* Evaluate some fulltext-search, catalog, etc integrations\n* Fix performance issues (?)\n* ... and fix (tons of) bugs! :D\n\n.. _Django-ZODB: http://triveos.github.com/django-zodb/\n.. _ZODB: http://pypi.python.org/pypi/ZODB3\n.. _Django: http://www.djangoproject.com/\n.. _RelStorage: http://pypi.python.org/pypi/RelStorage/\n.. _MySQLdb: http://pypi.python.org/pypi/MySQL-python/\n.. _MySQL: http://www.mysql.com/\n.. _psycopg2: http://pypi.python.org/pypi/psycopg2/\n.. _PostgreSQL: http://www.postgresql.org/\n.. _cx_Oracle: http://pypi.python.org/pypi/cx_Oracle/\n.. _Oracle: http://www.oracle.com/\n.. _coverage: http://pypi.python.org/pypi/coverage/\n.. _repoze.zodbconn: http://docs.repoze.org/zodbconn/\n.. _ZODB Tutorial: http://www.zodb.org/documentation/tutorial.html\n.. _ZODB programming guide: http://www.zodb.org/documentation/guide/index.html\n.. _Traversal: http://docs.repoze.org/bfg/current/narr/traversal.html\n.. _Repoze.BFG documentation: http://docs.repoze.org/bfg/1.3/\n.. _Pyramid: http://docs.pylonshq.com/pyramid/dev/", "description_content_type": null, "docs_url": null, "download_url": "http://github.com/triveos/django-zodb/downloads", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://triveos.github.com/django-zodb/", "keywords": null, "license": "BSD", "maintainer": null, "maintainer_email": null, "name": "django-zodb", "package_url": "https://pypi.org/project/django-zodb/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/django-zodb/", "project_urls": { "Download": "http://github.com/triveos/django-zodb/downloads", "Homepage": "http://triveos.github.com/django-zodb/" }, "release_url": "https://pypi.org/project/django-zodb/0.2/", "requires_dist": null, "requires_python": null, "summary": "Using Django and ZODB together", "version": "0.2" }, "last_serial": 1736684, "releases": { "0.2": [ { "comment_text": "", "digests": { "md5": "605bd68155e59423cb93ec19eb4742b5", "sha256": "e872695c0337839e3ad3e6ef41a0bf543c23677532bc4a40a47949074c47275f" }, "downloads": -1, "filename": "django-zodb-0.2.tar.gz", "has_sig": false, "md5_digest": "605bd68155e59423cb93ec19eb4742b5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29475, "upload_time": "2015-09-24T19:21:44", "url": "https://files.pythonhosted.org/packages/65/d2/6dec73463fd1e70deed08ab40233e5f454ab96cc387b7d2fe1c512f90fb9/django-zodb-0.2.tar.gz" } ], "0.2rc1": [], "0.2rc2": [], "0.2rc4": [ { "comment_text": "", "digests": { "md5": "742ce33602910df2afd947cb103a59a9", "sha256": "10dec5002d3fc1507344981e38d88b2d01852ce1f33f5ac77880fecb3bdfc185" }, "downloads": -1, "filename": "django-zodb-0.2rc4.tar.gz", "has_sig": false, "md5_digest": "742ce33602910df2afd947cb103a59a9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29059, "upload_time": "2015-09-24T19:21:39", "url": "https://files.pythonhosted.org/packages/d8/98/39c860cdfacd0193e930ee4b703288727ba597a25fb8c9dc2ba7546bde3f/django-zodb-0.2rc4.tar.gz" } ], "0.3dev": [ { "comment_text": "", "digests": { "md5": "9c87f6c6f58cd8f72e40c51a254b9c79", "sha256": "c62ad185db40dcfbdb6c76ac5da20a35efdb6481f3a62f4c0a83c9363cf2320c" }, "downloads": -1, "filename": "django-zodb-0.3dev.tar.gz", "has_sig": false, "md5_digest": "9c87f6c6f58cd8f72e40c51a254b9c79", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29573, "upload_time": "2010-11-29T21:13:59", "url": "https://files.pythonhosted.org/packages/ae/cb/493896dbcd24184f06e6d57af3ec9304fda40a70da155f8fc42d2a8d6812/django-zodb-0.3dev.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "605bd68155e59423cb93ec19eb4742b5", "sha256": "e872695c0337839e3ad3e6ef41a0bf543c23677532bc4a40a47949074c47275f" }, "downloads": -1, "filename": "django-zodb-0.2.tar.gz", "has_sig": false, "md5_digest": "605bd68155e59423cb93ec19eb4742b5", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 29475, "upload_time": "2015-09-24T19:21:44", "url": "https://files.pythonhosted.org/packages/65/d2/6dec73463fd1e70deed08ab40233e5f454ab96cc387b7d2fe1c512f90fb9/django-zodb-0.2.tar.gz" } ] }