{ "info": { "author": "abetkin", "author_email": "abvit89@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4" ], "description": "__What it is:__\n\nA lightweight package for django which does the filtering of django querysets. The central object - a filter - is a callable that takes a queryset as a parameter and returns a queryset:\n\n filtered_queryset = filtr(Model.objects.all())\n\nDjango itself has a similar object - Q-object (`django.db.models.Q`). Q-objects can be combined toghether (with `|`, `&` operations) or inverted (`~`) and then passed to `queryset.filter`.\n\nWith `qfilters`, what you get in the most common case, is just a wrapper around the Q-object. However there are __2 features__ that may be the reasons to use the package:\n \n__1. Support for additional filter types.__\n\nFor example, there is `ValuesDictFilter`, that is constructed from a field list, that will be passed to `queryset.values` and retrieve a list of dictionaries, and a filtering function, which accepts that dict as a parameter.\n\nThis filters can be combined or inverted in the same way Q-objects do, so that using multiple filters would result in a single call to `queryset.values`.\n\nThis is what it looks like in practice (all examples are taken from the `qfilter` testsuite):\n \n @ValuesDictFilter('@', fields_list=['traits__good_hunter'])\n def nas_i_zdes_neploho_kormyat(obj):\n return obj['traits__good_hunter'] is False # because it can be None\n \n cats = nas_i_zdes_neploho_kormyat(self.CatsBreed.objects.all())\n assert cats.exists()\n \nThere are also exotic variants (`qfilters.exotic_types`) like `QuerysetIterationHook`, which appends attributes to objects when queryset is iterated over. Another one is `PropertyBasedFilter`, which can access object's attributes and even properties like it were a regular django model object. The implementation is not very straightforward, still it passes the tests so far. Here is what it looks like:\n \n class CatsBreed(models.Model):\n # ...\n traits = models.OneToOneField('Traits')\n\n class Traits(models.Model):\n #...\n weight_min = models.FloatField(u'\u0412\u0435\u0441 \u043e\u0442, \u043a\u0433', null=True)\n weight_max = models.FloatField(u'\u0412\u0435\u0441 \u0434\u043e, \u043a\u0433', null=True)\n # if you can't specify min and max \n weight = models.FloatField(u'\u0412\u0435\u0441, \u043a\u0433', null=True)\n\n @property\n def kg(self):\n return self.weight or self.weight_max\n \n \n from qfilters import PropertyBasedFilter\n \n @PropertyBasedFilter('@',\n fields_list=['traits__weight', 'traits__weight_max'], \n properties=['traits.kg'])\n def light_cats(obj):\n return not obj.traits.kg or obj.traits.kg < 3\n \n assert light_cats(CatsBreed.objects.all()).exists()\n\n__2. Using class as container: methods are filters__\n\nIt is convenient to have an object, which can hold some context (for example, the view itself),\nand let the methods be filters, and be able to access this context. `qfilters.containers` provide this functionality, specifically, there is a `MethodFilter` class:\n \n from qfilter import MethodFilter\n \n class ManyFilters(MethodFilter):\n \n def filter__q(self):\n return Q(name__in=[u'\u0421\u0438\u0430\u043c\u0441\u043a\u0430\u044f', u'\u041d\u043e\u0440\u0432\u0435\u0436\u0441\u043a\u0430\u044f \u043b\u0435\u0441\u043d\u0430\u044f'])\n \n @make_filter(PropertyBasedFilter,\n fields_list=['traits__weight', 'traits__weight_max'], \n properties=['traits.kg'])\n def filter__big(self, cat):\n return cat.traits.kg and cat.traits.kg > 5\n \n def filter__q_yet_another(self):\n return Q(name__in=[u'\u041f\u0435\u0440\u0441\u0438\u0434\u0441\u043a\u0430\u044f', u'\u041d\u043e\u0440\u0432\u0435\u0436\u0441\u043a\u0430\u044f \u043b\u0435\u0441\u043d\u0430\u044f'])\n \n filters = ManyFilters()\n cat = filters(CatsBreed.objects.all())[0]\n\nThe idea was born from the experience of using the [django-rest-framework](http://www.django-rest-framework.org/). There is a notion of filter backend (a class) which every view knows about. First I implemented a simple method-based filter backend, the possible return values for the methods were eiher a Q-object or a queryset. But then I got difficulties with debugging since the return value doesn't even know which method it came from. Thus, I decided it will be a good idea to have this filter obbject.\n\nP.S. `qfilters` does not provide a filter backend to use with django-rest-framework, but it's a piece of cake to write one.", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/abetkin/django-qfilter", "keywords": "django filters", "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "qfilters", "package_url": "https://pypi.org/project/qfilters/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/qfilters/", "project_urls": { "Download": "UNKNOWN", "Homepage": "https://github.com/abetkin/django-qfilter" }, "release_url": "https://pypi.org/project/qfilters/0.1/", "requires_dist": null, "requires_python": null, "summary": "Filters for django", "version": "0.1" }, "last_serial": 1096351, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "a1eafa2b7a3a7fc35eb935c5e9005b79", "sha256": "133dec0f29b65e4e0bd4d53642311b9a35717e10433382a9dbdf3e0a7af1c128" }, "downloads": -1, "filename": "qfilters-0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a1eafa2b7a3a7fc35eb935c5e9005b79", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 10821, "upload_time": "2014-05-18T17:28:34", "url": "https://files.pythonhosted.org/packages/e8/4c/98679171705941f1c9c547e1e71e32f2ffb2962e1539ec5339ab02969da9/qfilters-0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "93e1cfb40b770e1aa9c1f72da805593e", "sha256": "6eae82b12314fc1e088104207eb8278f2a21f5d05b679fc8c27bff4eba9f8eff" }, "downloads": -1, "filename": "qfilters-0.1.tar.gz", "has_sig": false, "md5_digest": "93e1cfb40b770e1aa9c1f72da805593e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7000, "upload_time": "2014-05-18T17:28:37", "url": "https://files.pythonhosted.org/packages/77/85/e4b935a186ed3735bc96a1b703f7d5dde271fcb5559108a2d67b15ffa937/qfilters-0.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "a1eafa2b7a3a7fc35eb935c5e9005b79", "sha256": "133dec0f29b65e4e0bd4d53642311b9a35717e10433382a9dbdf3e0a7af1c128" }, "downloads": -1, "filename": "qfilters-0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "a1eafa2b7a3a7fc35eb935c5e9005b79", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 10821, "upload_time": "2014-05-18T17:28:34", "url": "https://files.pythonhosted.org/packages/e8/4c/98679171705941f1c9c547e1e71e32f2ffb2962e1539ec5339ab02969da9/qfilters-0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "93e1cfb40b770e1aa9c1f72da805593e", "sha256": "6eae82b12314fc1e088104207eb8278f2a21f5d05b679fc8c27bff4eba9f8eff" }, "downloads": -1, "filename": "qfilters-0.1.tar.gz", "has_sig": false, "md5_digest": "93e1cfb40b770e1aa9c1f72da805593e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7000, "upload_time": "2014-05-18T17:28:37", "url": "https://files.pythonhosted.org/packages/77/85/e4b935a186ed3735bc96a1b703f7d5dde271fcb5559108a2d67b15ffa937/qfilters-0.1.tar.gz" } ] }