{ "info": { "author": "Lex Berezhny", "author_email": "lex@damoti.com", "bugtrack_url": null, "classifiers": [ "Framework :: Django", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Topic :: Database", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "|pypi| |travis| |coverage|\n\n=====================\ndjango-tsvector-field\n=====================\n\n.. _introduction:\n\n**django-tsvector-field** is a drop-in replacement for Django's\n``django.contrib.postgres.search.SearchVectorField`` field that manages the\ndatabase triggers to keep your search field updated automatically in\nthe background.\n\n\nInstallation\n============\n\n.. _installation:\n\n**Python 3+**, **Django 1.11+** and **psycopg2** are the only requirements.\n\nInstall **django-tsvector-field** with your favorite python tool, e.g. ``pip install django-tsvector-field``.\n\nYou have two options to integrate it into your project:\n\n1. Simply add ``tsvector_field`` to your ``INSTALLED_APPS`` and start using it. This method\n uses Django's ``pre_migrate`` signal to inject the database operations into\n your migrations. This will work fine for many use cases.\n\n However, you'll run into issues with this method if you have unmigrated apps\n or you have disabled migrations for your unit tests. The problem is related\n to the fact that Django does not send ``pre_migrate`` signal for apps that\n do not have explicit migrations.\n\n2. Less simple but more reliable method is to create your own database engine module\n referencing ``tsvector_field.DatabaseSchemaEditor``. This will ensure that the\n database triggers are reliably created and dropped for all methods of migration.\n\n Create a 'db' directory in your Django project with an ``__init__.py`` and a ``base.py``\n with the following contents:\n\n\n .. code-block:: python\n\n from django.db.backends.postgresql import base\n import tsvector_field\n\n class DatabaseWrapper(base.DatabaseWrapper):\n SchemaEditorClass = tsvector_field.DatabaseSchemaEditor\n\n\n Then update the ``'ENGINE'`` configuration in your ``DATABASES`` setting. For example,\n if your project is called ``my_project`` and it has the ``db`` module as described\n above, then change your ``DATABASE`` setting to have the following ``'ENGINE'`` configuration:\n\n\n .. code-block:: python\n\n DATABASES = {\n 'default': {\n 'ENGINE': 'my_project.db',\n }\n }\n\nUsage\n=====\n\n.. _usage:\n\n``tsvector_field.SearchVectorField`` works like any other Django field: add it to your model,\nrun ``makemigrations``, run ``migrate`` and ``tsvector_field`` will take care to create the\npostgres trigger and stored procedure.\n\nTo illustrate how this works we'll create a ``TextDocument`` model with a\n``tsvector_field.SearchVectorField`` field and two textual fields to be used as\ninputs for the full text search.\n\n.. code-block:: python\n\n from django.db import models\n import tsvector_field\n\n class TextDocument(models.Model):\n title = models.CharField(max_length=128)\n body = models.TextField()\n search = tsvector_field.SearchVectorField([\n tsvector_field.WeightedColumn('title', 'A'),\n tsvector_field.WeightedColumn('body', 'D'),\n ], 'english')\n\n\nAfter you've migrated you can create some ``TextDocument`` records and see that\npostgres keeps it synchronized in the background. Specifically, because the\n``search`` field is updated at the database level, you'll need to call ``refresh_from_db()``\nto see the new value after a ``.save()`` or ``.create()``.\n\n\n.. code-block:: python\n\n >>> doc = TextDocument.objects.create(\n ... title=\"My hovercraft is full of spam.\",\n ... body=\"It's what eels love!\"\n ... )\n >>> doc.search\n >>> doc.refresh_from_db()\n >>> doc.search\n \"'eel':10 'full':4A 'hovercraft':2A 'love':11 'spam':6A\"\n\n\nNote that ``spam`` is recorded with ``6A``, this will be important later. Let's\ncontinue with the previous session and create another document.\n\n\n.. code-block:: python\n\n >>> doc = TextDocument.objects.create(\n ... title=\"What do eels eat?\",\n ... body=\"Spam, spam, spam, they love spam!\"\n ... )\n >>> doc.refresh_from_db()\n >>> doc.search\n \"'eat':4A 'eel':3A 'love':9 'spam':5,6,7,10\"\n\n\nNow we have two documents: first document has just one ``spam`` with weight ``A`` and\nthe second document has 4 ``spam`` with lower weight. If we search for ``spam`` and apply\na search rank then the ``A`` weight on the first document will cause that document to\nappear higher in the results.\n\n\n.. code-block:: python\n\n >>> from django.contrib.postgres.search import SearchQuery, SearchRank\n >>> from django.db.models.expressions import F\n >>> matches = TextDocument.objects\\\n ... .annotate(rank=SearchRank(F('search'), SearchQuery('spam')))\\\n ... .order_by('-rank')\\\n ... .values_list('rank', 'title', 'body')\n >>> for match in matches:\n ... print(match)\n ...\n (0.607927, 'My hovercraft is full of spam.', \"It's what eels love!\")\n (0.0865452, 'What do eels eat?', 'Spam, spam, spam, they love spam!')\n\n\nIf you are only interested in getting a list of possible matches without ranking\nyou can filter directly on the search column like so:\n\n.. code-block:: python\n\n >>> TextDocument.objects.filter(search='spam')\n , ]>\n\nFinal note about the ``tsvector_field.SearchVectorField`` field is that it takes a\n``language_column`` argument instead of or in addition to the ``language`` argument. When\nboth arguments are provided then the database trigger will first look up the value in the\n``language_column`` and if that is null it will use the language in ``language``.\n\nMigrating\n=========\n\n.. _migrating:\n\nWhen adding a ``tsvector_field.SearchVectorField`` field to an existing model you likely\nwant to update the search vector for all existing records. **django-tsvector-field** includes\nthe ``tsvector_field.IndexSearchVector`` operation that takes the model name and search vector\ncolumn as arguments. If we had previously created the ``TextDocument`` without a ``search`` column\nthen to add search capability we would use the following migration:\n\n.. code-block:: python\n\n from django.db import migrations, models\n import tsvector_field\n\n class Migration(migrations.Migration):\n\n dependencies = []\n\n operations = [\n migrations.AddField(\n model_name='textdocument',\n name='search',\n field=tsvector_field.SearchVectorField(columns=[\n tsvector_field.WeightedColumn('title', 'A'),\n tsvector_field.WeightedColumn('body', 'D')\n ], language='english'),\n ),\n tsvector_field.IndexSearchVector('textdocument', 'search'),\n ]\n\n\nFor more information on querying, see the Django documentation on Full Text Search:\n\nhttps://docs.djangoproject.com/en/dev/ref/contrib/postgres/search/\n\nFor more information on configuring how the searches work, see PostgreSQL docs:\n\nhttps://www.postgresql.org/docs/devel/static/textsearch.html\n\n\n.. |pypi| image:: https://img.shields.io/pypi/v/django-tsvector-field.svg\n :target: https://pypi.python.org/pypi/django-tsvector-field\n :alt: Package\n\n.. |travis| image:: https://travis-ci.org/damoti/django-tsvector-field.svg?branch=master\n :target: https://travis-ci.org/damoti/django-tsvector-field\n :alt: Build\n\n.. |coverage| image:: https://codecov.io/gh/damoti/django-tsvector-field/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/damoti/django-tsvector-field\n :alt: Test Coverage\n\n\n0.9.4\n-----\n\n* Initial support django 2.0 alpha\n\n0.9.3\n-----\n\n* Automatically create GIN index on tsvector column\n\n0.9.2\n-----\n\n* IndexSearchVector migration operation added\n* documentation fixes\n* Added support for both pre_migrate signal based integration and extending DatabaseSchemaEditor\n\n0.9.1\n-----\n\n* Fixed bug with AlterField migrations.\n\n0.9.0\n-----\n\n* Initial release.\n", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/damoti/django-tsvector-field", "keywords": "django", "license": "BSD", "maintainer": "", "maintainer_email": "", "name": "django-tsvector-field", "package_url": "https://pypi.org/project/django-tsvector-field/", "platform": "", "project_url": "https://pypi.org/project/django-tsvector-field/", "project_urls": { "Homepage": "https://github.com/damoti/django-tsvector-field" }, "release_url": "https://pypi.org/project/django-tsvector-field/0.9.4/", "requires_dist": null, "requires_python": "", "summary": "Django field implementation for PostgreSQL tsvector.", "version": "0.9.4" }, "last_serial": 3178289, "releases": { "0.9.0": [ { "comment_text": "", "digests": { "md5": "701fb3dc182da836758068dc09248524", "sha256": "3d7c930e3ccf749c5ae8eef997de06c4c8e5bcf00c764cc3a7c06bd128df5fd5" }, "downloads": -1, "filename": "django_tsvector_field-0.9.0-py3-none-any.whl", "has_sig": false, "md5_digest": "701fb3dc182da836758068dc09248524", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 9587, "upload_time": "2016-12-13T16:36:23", "url": "https://files.pythonhosted.org/packages/16/a4/7070e2c6dd5ad3897758c788e79a85197653bdeadde9c57fc3756d6b9403/django_tsvector_field-0.9.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5ae9a1001f499be116b5b1bb644c6aec", "sha256": "587f627949fd1dd046584ef3197fa844e5fe7c32a8b6d30d3bfba112ad51db91" }, "downloads": -1, "filename": "django-tsvector-field-0.9.0.tar.gz", "has_sig": false, "md5_digest": "5ae9a1001f499be116b5b1bb644c6aec", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 6987, "upload_time": "2016-12-13T16:34:37", "url": "https://files.pythonhosted.org/packages/d9/98/878473435798221ab18ad898b77cd73d9fbfccab9445d59f8cdbd8f1b0db/django-tsvector-field-0.9.0.tar.gz" } ], "0.9.1": [ { "comment_text": "", "digests": { "md5": "d9ede47fa59003b48ae4171fe012de42", "sha256": "df8fbfb081f197c4b193b929fad2fe097334641912ed55c58925a7fdb6c85add" }, "downloads": -1, "filename": "django_tsvector_field-0.9.1-py3-none-any.whl", "has_sig": false, "md5_digest": "d9ede47fa59003b48ae4171fe012de42", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 9814, "upload_time": "2016-12-13T17:28:34", "url": "https://files.pythonhosted.org/packages/da/52/a2920507ddfc02f88abcd8a80fa103ec2c9679202be863c16961ca915652/django_tsvector_field-0.9.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "11174d02cde4cb2e79498124ac54e0a1", "sha256": "3f229edb52539539e554d587581a5c102028d29627b8412cf4b04497301fb467" }, "downloads": -1, "filename": "django-tsvector-field-0.9.1.tar.gz", "has_sig": false, "md5_digest": "11174d02cde4cb2e79498124ac54e0a1", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7112, "upload_time": "2016-12-13T17:28:33", "url": "https://files.pythonhosted.org/packages/24/7d/d1eb0e08e4b8569f8a807b10ec82e52c0fe0f375b5c98c8bcb7d73ce7407/django-tsvector-field-0.9.1.tar.gz" } ], "0.9.2": [ { "comment_text": "", "digests": { "md5": "3392498095373e02932c203f3c47fafd", "sha256": "b1e0c81f0ce8002438d265e8e8c7abf45b218c8a33cb00ec7747cefc2520b58d" }, "downloads": -1, "filename": "django_tsvector_field-0.9.2-py3-none-any.whl", "has_sig": false, "md5_digest": "3392498095373e02932c203f3c47fafd", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 13905, "upload_time": "2016-12-16T16:31:54", "url": "https://files.pythonhosted.org/packages/04/dc/a1aad3a02e2b232b029fb25e1dd3f371dbec701e75942e83d2cd6b6d4a35/django_tsvector_field-0.9.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "44b49c611258ad54f88d5a9191043873", "sha256": "64f789543707bdbc176092967372e8815a46cc5c6fccaff6ef1e8d0b8278d282" }, "downloads": -1, "filename": "django-tsvector-field-0.9.2.tar.gz", "has_sig": false, "md5_digest": "44b49c611258ad54f88d5a9191043873", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11266, "upload_time": "2016-12-16T16:31:52", "url": "https://files.pythonhosted.org/packages/86/4d/7f81655823c166c832e76ebcd2a031ad41cd9cdab22923eb55084e0bcaa0/django-tsvector-field-0.9.2.tar.gz" } ], "0.9.3": [ { "comment_text": "", "digests": { "md5": "d6544e975c761c623c23c44428a82ae4", "sha256": "b24bf56d06d923df2a15bf8d3a3271e76d23740907621119432f52af60765f98" }, "downloads": -1, "filename": "django_tsvector_field-0.9.3-py3-none-any.whl", "has_sig": false, "md5_digest": "d6544e975c761c623c23c44428a82ae4", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 14025, "upload_time": "2016-12-19T00:47:32", "url": "https://files.pythonhosted.org/packages/36/78/2cb8ee7a2de3c9767c8d43dd4eccf75bfb6567a18bb8183ea0bf216649ae/django_tsvector_field-0.9.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f8c85bd7dee0b7737b23728466a97407", "sha256": "5da713c07a1b7dad2f279867f5269a139676a752a6069fa3b7e40987c8345622" }, "downloads": -1, "filename": "django-tsvector-field-0.9.3.tar.gz", "has_sig": false, "md5_digest": "f8c85bd7dee0b7737b23728466a97407", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 11352, "upload_time": "2016-12-19T00:47:30", "url": "https://files.pythonhosted.org/packages/7d/b5/01acdbcde181dab84fbbe76e5413089374114c2c2f67d65aa16e8540feae/django-tsvector-field-0.9.3.tar.gz" } ], "0.9.4": [ { "comment_text": "", "digests": { "md5": "5d6e3bd65b00feca33ecdbf6e1f200ea", "sha256": "17dab5d9a78f6f3718d846e3d2e8412cabbfe251f6f592bcd5b70cfca19f906f" }, "downloads": -1, "filename": "django_tsvector_field-0.9.4-py3-none-any.whl", "has_sig": false, "md5_digest": "5d6e3bd65b00feca33ecdbf6e1f200ea", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 14484, "upload_time": "2017-09-16T04:25:30", "url": "https://files.pythonhosted.org/packages/95/8c/458f41b375e15659f3cc12d0d23a5d2645b05660a89f8938bb41c3409dfb/django_tsvector_field-0.9.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d254abcba678662f707bde0d551037ad", "sha256": "6bd6db94d30928396d7c751187165eb8bfa98d0a2d205836578a8e5133ad81af" }, "downloads": -1, "filename": "django-tsvector-field-0.9.4.tar.gz", "has_sig": false, "md5_digest": "d254abcba678662f707bde0d551037ad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10180, "upload_time": "2017-09-16T04:25:27", "url": "https://files.pythonhosted.org/packages/d2/90/a0c32936279410f815895c71a3229c1ddcc536b96277838467862753e1d3/django-tsvector-field-0.9.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "5d6e3bd65b00feca33ecdbf6e1f200ea", "sha256": "17dab5d9a78f6f3718d846e3d2e8412cabbfe251f6f592bcd5b70cfca19f906f" }, "downloads": -1, "filename": "django_tsvector_field-0.9.4-py3-none-any.whl", "has_sig": false, "md5_digest": "5d6e3bd65b00feca33ecdbf6e1f200ea", "packagetype": "bdist_wheel", "python_version": "3.5", "requires_python": null, "size": 14484, "upload_time": "2017-09-16T04:25:30", "url": "https://files.pythonhosted.org/packages/95/8c/458f41b375e15659f3cc12d0d23a5d2645b05660a89f8938bb41c3409dfb/django_tsvector_field-0.9.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "d254abcba678662f707bde0d551037ad", "sha256": "6bd6db94d30928396d7c751187165eb8bfa98d0a2d205836578a8e5133ad81af" }, "downloads": -1, "filename": "django-tsvector-field-0.9.4.tar.gz", "has_sig": false, "md5_digest": "d254abcba678662f707bde0d551037ad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10180, "upload_time": "2017-09-16T04:25:27", "url": "https://files.pythonhosted.org/packages/d2/90/a0c32936279410f815895c71a3229c1ddcc536b96277838467862753e1d3/django-tsvector-field-0.9.4.tar.gz" } ] }