{ "info": { "author": "OmenApps", "author_email": "support@omenapps.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 2 - Pre-Alpha", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 2.0", "Framework :: Django :: 2.1", "Framework :: Django :: 2.2", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "django-common-user-tenants\n==========================\n\nTHIS APP IS NOT READY FOR PRODUCTION. IT IS A WORK IN PROGRESS COMBINING DJANGO-TENANTS AND DJANGO-TENANT-USERS WITH ADDITIONAL FEATURES AND UTILITIES.\n\n====\n\nThis application enables `django`_ powered websites to have multiple\ntenants via `PostgreSQL schemas`_. A vital feature for every\nSoftware-as-a-Service (SaaS) website.\n\n Read the full documentaion here: `django-tenants.readthedocs.org`_\n\nDjango provides currently no simple way to support multiple tenants\nusing the same project instance, even when only the data is different.\nBecause we don\u2019t want you running many copies of your project, you\u2019ll be\nable to have:\n\n- Multiple customers running on the same instance\n- Shared and Tenant-Specific data\n- Tenant View-Routing\n\n\n\nWhat are schemas\n----------------\n\nA schema can be seen as a directory in an operating system, each\ndirectory (schema) with it\u2019s own set of files (tables and objects). This\nallows the same table name and objects to be used in different schemas\nwithout conflict. For an accurate description on schemas, see\n`PostgreSQL\u2019s official documentation on schemas`_.\n\nWhy schemas\n-----------\n\nThere are typically three solutions for solving the multitenancy\nproblem.\n\n1. Isolated Approach: Separate Databases. Each tenant has it\u2019s own\n database.\n\n2. Semi Isolated Approach: Shared Database, Separate Schemas. One\n database for all tenants, but one schema per tenant.\n\n3. Shared Approach: Shared Database, Shared Schema. All tenants share\n the same database and schema. There is a main tenant-table, where all\n other tables have a foreign key pointing to.\n\nThis application implements the second approach, which in our opinion,\nrepresents the ideal compromise between simplicity and performance.\n\n- Simplicity: barely make any changes to your current code to support\n multitenancy. Plus, you only manage one database.\n- Performance: make use of shared connections, buffers and memory.\n\nEach solution has it\u2019s up and down sides, for a more in-depth\ndiscussion, see Microsoft\u2019s excellent article on `Multi-Tenant Data\nArchitecture`_.\n\nHow it works\n------------\n\nTenants are identified via their host name (i.e tenant.domain.com). This\ninformation is stored on a table on the ``public`` schema. Whenever a\nrequest is made, the host name is used to match a tenant in the\ndatabase. If there\u2019s a match, the search path is updated to use this\ntenant\u2019s schema. So from now on all queries will take place at the\ntenant\u2019s schema. For example, suppose you have a tenant ``customer`` at\nhttp://customer.example.com. Any request incoming at\n``customer.example.com`` will automatically use ``customer``\\ \u2019s schema\nand make the tenant available at the request. If no tenant is found, a\n404 error is raised. This also means you should have a tenant for your\nmain domain, typically using the ``public`` schema. For more information\nplease read the `setup`_ section.\n\nWhat can this app do?\n---------------------\n\nAs many tenants as you want\n~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nEach tenant has its data on a specific schema. Use a single project\ninstance to serve as many as you want.\n\nTenant-specific and shared apps\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nTenant-specific apps do not share their data between tenants, but you\ncan also have shared apps where the information is always available and\nshared between all.\n\nTenant View-Routing\n~~~~~~~~~~~~~~~~~~~\n\nYou can have different views for ``http://customer.example.com/`` and\n``http://example.com/``, even though Django only uses the string after\nthe host name to identify which view to serve.\n\nMagic\n~~~~~\n\nEveryone loves magic! You\u2019ll be able to have all this barely having to\nchange your code!\n\nSetup & Documentation\n---------------------\n\n**This is just a short setup guide**, it is **strongly** recommended\nthat you read the complete version at\n`django-tenants.readthedocs.org`_.\n\nYour ``DATABASE_ENGINE`` setting needs to be changed to\n\n.. code-block:: python\n\n DATABASES = {\n 'default': {\n 'ENGINE': 'django_tenants.postgresql_backend',\n # ..\n }\n } \n\nAdd the middleware ``django_tenants.middleware.main.TenantMainMiddleware`` to the\ntop of ``MIDDLEWARE``, so that each request can be set to use\nthe correct schema.\n\n.. code-block:: python\n\n MIDDLEWARE = (\n 'django_tenants.middleware.main.TenantMainMiddleware',\n #...\n )\n\nAdd ``django_tenants.routers.TenantSyncRouter`` to your `DATABASE_ROUTERS`\nsetting, so that the correct apps can be synced, depending on what's \nbeing synced (shared or tenant).\n\n.. code-block:: python\n\n DATABASE_ROUTERS = (\n 'django_tenants.routers.TenantSyncRouter',\n )\n\nAdd ``django_tenants`` to your ``INSTALLED_APPS``.\n\nCreate your tenant model\n~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n from django.db import models\n from django_tenants.models import TenantMixin, DomainMixin\n\n class Client(TenantMixin):\n name = models.CharField(max_length=100)\n paid_until = models.DateField()\n on_trial = models.BooleanField()\n created_on = models.DateField(auto_now_add=True)\n\n class Domain(DomainMixin):\n pass\n\nDefine on ``settings.py`` which model is your tenant model. Assuming you\ncreated ``Client`` inside an app named ``customers``, your\n``TENANT_MODEL`` should look like this:\n\n.. code-block:: python\n\n TENANT_MODEL = \"customers.Client\" # app.Model\n TENANT_DOMAIN_MODEL = \"customers.Domain\" # app.Model\n\nNow run ``migrate_schemas``, this will sync your apps to the ``public``\nschema.\n\n.. code-block:: bash\n\n python manage.py migrate_schemas --shared\n\nCreate your tenants just like a normal django model. Calling ``save``\nwill automatically create and sync the schema.\n\n.. code-block:: python\n\n from customers.models import Client, Domain\n\n # create your public tenant\n tenant = Client(schema_name='tenant1',\n name='My First Tenant',\n paid_until='2014-12-05',\n on_trial=True)\n tenant.save()\n\n # Add one or more domains for the tenant\n domain = Domain()\n domain.domain = 'tenant.my-domain.com'\n domain.tenant = tenant\n domain.is_primary = True\n domain.save()\n\nAny request made to ``tenant.my-domain.com`` will now automatically set\nyour PostgreSQL\u2019s ``search_path`` to ``tenant1`` and ``public``, making\nshared apps available too. This means that any call to the methods\n``filter``, ``get``, ``save``, ``delete`` or any other function\ninvolving a database connection will now be done at the tenant\u2019s schema,\nso you shouldn\u2019t need to change anything at your views.\n\nYou\u2019re all set, but we have left key details outside of this short\ntutorial, such as creating the public tenant and configuring shared and\ntenant specific apps. Complete instructions can be found at\n`django-tenants.readthedocs.org`_.\n\n\n\nRunning the example project\n---------------------------\n\ndjango-tenants comes with an example project please see\n\n`examples`_.\n\n\nCredits\n-------\n\nI would like to thank two of the original authors of this project.\n\n1. Bernardo Pires under the name `django-tenant-schemas`_.\n\n2. Vlada Macek under the name of `django-schemata`_.\n\nRequirements\n------------\n\n - Django 2 if you want to use Django 1.11 or lower please use version 1 of django-tenants\n - PostgreSQL\n\nTesting\n-------\n\nIf you want to run test you can either run ``run_tests.sh`` (which requires access to\na PostgreSQL instance, location of which you can customize using the ``DATABASE_HOST``\nenv variable) or use `docker-compose`_ like this:\n\n.. code-block:: bash\n\n ## Start Docker service\n # start docker # with Upstart\n # systemctl start docker # with systemd\n\n ## Install docker-compose (you might want to do this in Python virtualenv)\n # pip install docker-compose\n\n ## In main directory of this repo do:\n docker-compose up postgres # starts dockerized PostgreSQL service\n docker-compose run django-tenants-test # runs django-tenants tests\n\n(note that upon first run the ``Dockerfile`` will be built).\n\nVideo Tutorial\n--------------\n\nAn online video tutorial is available on `youtube`_.\n\nDonation\n--------\n\nIf this project help you reduce time to develop, you can give me cake :)\n\n.. image:: https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif\n :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=QU8BGC7DWB9G6&source=ur\n\n\n.. _youtube: https://youtu.be/NsWlUMTfIFo\n.. _django: https://www.djangoproject.com/\n.. _PostgreSQL schemas: http://www.postgresql.org/docs/9.1/static/ddl-schemas.html\n.. _PostgreSQL\u2019s official documentation on schemas: http://www.postgresql.org/docs/9.1/static/ddl-schemas.html\n.. _Multi-Tenant Data Architecture: http://msdn.microsoft.com/en-us/library/aa479086.aspx\n.. _setup: https://django-tenants.readthedocs.org/en/latest/install.html\n.. _examples: https://django-tenants.readthedocs.org/en/latest/examples.html\n.. _django-tenants.readthedocs.org: https://django-tenants.readthedocs.org/en/latest/\n.. _django-tenant-schemas: http://github.com/bernardopires/django-tenant-schemas\n.. _django-schemata: https://github.com/tuttle/django-schemata\n.. _docker-compose: https://docs.docker.com/engine/reference/run/\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/OmenApps/django-common-user-tenants", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "django-common-user-tenants", "package_url": "https://pypi.org/project/django-common-user-tenants/", "platform": "", "project_url": "https://pypi.org/project/django-common-user-tenants/", "project_urls": { "Homepage": "https://github.com/OmenApps/django-common-user-tenants" }, "release_url": "https://pypi.org/project/django-common-user-tenants/0.0.26/", "requires_dist": [ "Django (<3.0,>=2.0)", "psycopg2" ], "requires_python": "", "summary": "Tenant support for Django using PostgreSQL schemas, with common users and multiple tenant types.", "version": "0.0.26" }, "last_serial": 5315320, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "6f3c2439d6a32ec3d820ef9c720444a5", "sha256": "c0c732f9cbb5274f694d3e18380494527de9da6d241fd580dd629a85fb920415" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "6f3c2439d6a32ec3d820ef9c720444a5", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 68888, "upload_time": "2019-05-07T04:21:22", "url": "https://files.pythonhosted.org/packages/56/e4/b4d18b21dd34ca126092ced9ca97320f6e87bc2612d78d6f5cceace96a97/django_common_user_tenants-0.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9da699732c0a43f3cb385b63f78fbd9b", "sha256": "6e88c700fe52035daa795f958e1e4b0b4c2a2d14a449fbca5a880f3af3d8eaad" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.1.tar.gz", "has_sig": false, "md5_digest": "9da699732c0a43f3cb385b63f78fbd9b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48553, "upload_time": "2019-05-07T04:21:25", "url": "https://files.pythonhosted.org/packages/85/7c/cee40cc006894941c948714b3d1d8c62ff23c7fcd0ccb77138f56fadd079/django-common-user-tenants-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "d975fae29c2a84dbdf89e7cbd8b46f4e", "sha256": "b49728d846edfc8b447cd07052e7b401fd0139c8139a9f5a934d7081f8475ead" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "d975fae29c2a84dbdf89e7cbd8b46f4e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 69010, "upload_time": "2019-05-07T22:31:21", "url": "https://files.pythonhosted.org/packages/9e/1e/eadcae9a51b29142e13bcb38157f362ff331b0c678df7eb916efdfc00efa/django_common_user_tenants-0.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f1c5709a222eaef55f36decd36da12c3", "sha256": "a5a11171f850a1c9fe2a7ca39155cac4f636bd9c4883e7307563f7899266a0b8" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.2.tar.gz", "has_sig": false, "md5_digest": "f1c5709a222eaef55f36decd36da12c3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48682, "upload_time": "2019-05-07T22:31:24", "url": "https://files.pythonhosted.org/packages/d6/5c/b6f42930d8a8b9e060a76e9f99056067eb51fc02d0db40ea1c0110434b15/django-common-user-tenants-0.0.2.tar.gz" } ], "0.0.26": [ { "comment_text": "", "digests": { "md5": "31cfcf20cd42525f5cc9f161362c840d", "sha256": "9c918ce573abac8fe8bc165dfd5cd1389f1a2ce15c1b462012a33dbfd720475f" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.26-py3-none-any.whl", "has_sig": false, "md5_digest": "31cfcf20cd42525f5cc9f161362c840d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 86079, "upload_time": "2019-05-25T03:57:25", "url": "https://files.pythonhosted.org/packages/76/ed/5a4c10756036d542f8d539f949406375affe5efdb46d5f6b448db2ea1227/django_common_user_tenants-0.0.26-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a978d8fd99d4acee4941043aace381cf", "sha256": "4a5fa30d6040e8769978634b89f61fdbffb66ee4161d1187287b6811803a6fc7" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.26.tar.gz", "has_sig": false, "md5_digest": "a978d8fd99d4acee4941043aace381cf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49386, "upload_time": "2019-05-25T03:57:31", "url": "https://files.pythonhosted.org/packages/d9/d4/877d1f5c991102458930c1d7681b2de0db6e0c125f2750451246ff29b5af/django-common-user-tenants-0.0.26.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "7193b2931fe8f1bcef58e4eeb0e7ed45", "sha256": "50f3071d280376805a282ee3d6308dc0c2f819dfa3694f6fd89032cfe302fd44" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "7193b2931fe8f1bcef58e4eeb0e7ed45", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 69012, "upload_time": "2019-05-07T23:04:55", "url": "https://files.pythonhosted.org/packages/ea/e5/901a69198541bb023d38e4207f3377bd38678bb47e8b2d37448b6ada5e65/django_common_user_tenants-0.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a833405553bb93d5e347ddad25c6daac", "sha256": "fa7090b79b141a2524562f73476bca9700dd73411c52faef9c602961717cb608" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.3.tar.gz", "has_sig": false, "md5_digest": "a833405553bb93d5e347ddad25c6daac", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48686, "upload_time": "2019-05-07T23:04:57", "url": "https://files.pythonhosted.org/packages/d1/f5/1c2b26f6bab9b42f6073a00207daf2387ef294e773b00438bb845a7ef303/django-common-user-tenants-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "634c58878b875a4eb12a0d3229a0b26d", "sha256": "cf4b8b873edab317fa8f0f545dd42182d5fdebd4fb11dcd475f9c2083018902c" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.4-py3-none-any.whl", "has_sig": false, "md5_digest": "634c58878b875a4eb12a0d3229a0b26d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 74803, "upload_time": "2019-05-19T00:49:55", "url": "https://files.pythonhosted.org/packages/49/07/7f832807eef13457ced3e30f8b1f4281ad4c0f6e8fcb0a9b9d333c1675b7/django_common_user_tenants-0.0.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "002dfdaf308ad53f9d96cfb1cabacb18", "sha256": "e79cc3656a80612062d319c0c538599e61dea66706b57982b8e70fb0b772c74b" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.4.tar.gz", "has_sig": false, "md5_digest": "002dfdaf308ad53f9d96cfb1cabacb18", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48297, "upload_time": "2019-05-19T00:49:59", "url": "https://files.pythonhosted.org/packages/ad/8b/ecf7cf93e9e41f772415449efdb9c886250bda493d9d5c01b1b0507a77ac/django-common-user-tenants-0.0.4.tar.gz" } ], "0.0.5": [ { "comment_text": "", "digests": { "md5": "17777e507057aa30737ddbd023c87a2e", "sha256": "f39f0e6c06b9157daac3e28975f897b75428cd5f8871442e56da6160324b4eb5" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.5-py3-none-any.whl", "has_sig": false, "md5_digest": "17777e507057aa30737ddbd023c87a2e", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 74719, "upload_time": "2019-05-19T01:02:58", "url": "https://files.pythonhosted.org/packages/5f/d1/16ec2eb945c94e3c52eda90634df6dcdb3c5229c013b6abeb4100303dd3f/django_common_user_tenants-0.0.5-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "abe6c6590751fc24ec4dedb776a1d86f", "sha256": "b26937e0f1f42cb4ace745f637d4530de9e5c2deed11ce19a8e7df63d6259223" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.5.tar.gz", "has_sig": false, "md5_digest": "abe6c6590751fc24ec4dedb776a1d86f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 48148, "upload_time": "2019-05-19T01:03:03", "url": "https://files.pythonhosted.org/packages/e1/86/b18d99d063157c26aafe5f9fae43f3be42d6ca2605b62502a3d4cf36d2ab/django-common-user-tenants-0.0.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "31cfcf20cd42525f5cc9f161362c840d", "sha256": "9c918ce573abac8fe8bc165dfd5cd1389f1a2ce15c1b462012a33dbfd720475f" }, "downloads": -1, "filename": "django_common_user_tenants-0.0.26-py3-none-any.whl", "has_sig": false, "md5_digest": "31cfcf20cd42525f5cc9f161362c840d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 86079, "upload_time": "2019-05-25T03:57:25", "url": "https://files.pythonhosted.org/packages/76/ed/5a4c10756036d542f8d539f949406375affe5efdb46d5f6b448db2ea1227/django_common_user_tenants-0.0.26-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a978d8fd99d4acee4941043aace381cf", "sha256": "4a5fa30d6040e8769978634b89f61fdbffb66ee4161d1187287b6811803a6fc7" }, "downloads": -1, "filename": "django-common-user-tenants-0.0.26.tar.gz", "has_sig": false, "md5_digest": "a978d8fd99d4acee4941043aace381cf", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 49386, "upload_time": "2019-05-25T03:57:31", "url": "https://files.pythonhosted.org/packages/d9/d4/877d1f5c991102458930c1d7681b2de0db6e0c125f2750451246ff29b5af/django-common-user-tenants-0.0.26.tar.gz" } ] }