{ "info": { "author": "Artem Yastrebkov", "author_email": "nerlin57@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.10", "Framework :: Django :: 1.11", "Framework :: Django :: 1.9", "Framework :: Django :: 2.0", "Intended Audience :: Developers", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Database" ], "description": "# Django Polymorphic QuerySet\nHelps to implement filtering logic depended on model type.\n\n*You should not confuse filtering and permission checking. If you need to get items based on user, you should probably\nuse Django Permissions.*\n\n## Installation\n`pip install django-polymorphic-queryset`\n\n## Motivation\n\nFor example, your application have two models: `Product` and derived from it `PerishableProduct`:\n\n```python\nfrom django.db import models\n\nclass Product(models.Model):\n name = models.CharField(max_length=120)\n\n\nclass PerishableProduct(Product):\n is_perished = models.BooleanField(default=False)\n\n\nclass BrokenProduct(Product):\n repaired = models.BooleanField(default=False)\n\n```\n\nIf you want to add a view that returns *active* products (products that are not perished and repaired) with \nthis hierarchy you will probably end with a one function that contains all that conditions:\n\n```python\nfrom django.db import models\n\nclass ProductQuerySet(models.QuerySet):\n def get_active_products(self):\n return self.filter(\n perishableproduct__is_perished=False,\n brokenproduct__repaired=True\n )\n```\n\nIn a big application with a lot of models and conditions this function can become complex and difficult to maintain.\nAlso, with this implementation base queryset will know about details of derived models.\n\nQuerySet filter methods can be separated in a parallel hierarchy, so that derived QuerySets will add a custom logic \nto base methods or override them:\n\n```python\n# Not a real example, just the idea.\n\nfrom django.db import models\n\nclass ProductQuerySet(models.QuerySet):\n def get_active_products(self):\n return self.all()\n\n\nclass PerishableProductQuerySet(ProductQuerySet):\n def get_active_products(self):\n return self.filter(is_perished=False)\n\n\nclass BrokenProductQuerySet(ProductQuerySet):\n def get_active_products(self):\n return self.filter(repaired=True)\n``` \n\nBut in this implementation `ProductQuerySet` will return all products including products that were saved\nas `PerishableProduct` with `is_perished` equal to `True` and `BrokenProduct` with `repaired` equal to `False`. \n\n## Solution\nThis library allows you to create polymorphic querysets that takes into account all conditions in a queryset \nhierarchy (*note that query functions belongs to class, not class instance, works as `@classmethod` decorator*):\n```python\nfrom polymorphic_queryset import Queryable, query\nfrom django.db import models\n\nclass ProductQuerySet(Queryable, models.QuerySet):\n model_name = \"Product\"\n\n @query()\n def get_active_products(cls):\n return query.all()\n\n\nclass PerishableProductQuerySet(ProductQuerySet):\n model_name = \"PerishableProduct\"\n\n @query()\n def get_active_products(cls):\n return models.Q(is_perished=False)\n\n\nclass BrokenProductQuerySet(ProductQuerySet):\n model_name = \"BrokenProduct\"\n\n @query()\n def get_active_products(cls):\n return models.Q(repaired=True)\n```\n\nThis implementation separates query conditions between different QuerySets based on a specified model name.\n`ProductQuerySet.get_active_products` will return any product that was saved as `Product`,\nproducts that were saved as `PerishableProduct` if `is_perished` is *False* and `BrokenProduct` is `repaired` is *True*.\nQuerySet will still return `Product` instances.\n\n*You can use **django-polymorphic** library to return instances of derived classes instead.*\n\nYou can now use these querysets as a model manager:\n```python\nfrom django.db import models\n\nclass Product(models.Model):\n objects = ProductQuerySet.as_manager()\n\n\nclass PerishableProduct(Product):\n objects = PerishableProductQuerySet.as_manager()\n\n\nclass BrokenProduct(Product):\n objects = BrokenProductQuerySet.as_manager()\n\n\nactive_products = Product.objects.get_active_products()\n```\n\nTo use conditions of base classes in your querysets you can call `conditions` function of your method decorated with `query`:\n```python\nfrom polymorphic_queryset import Queryable, query\nfrom django.db import models\nimport datetime\n\n\nclass ProductQuerySet(Queryable, models.QuerySet):\n model_name = \"Product\"\n\n @query()\n def get_new_products(cls):\n return models.Q(date_created__gte=datetime.datetime.now() - datetime.timedelta(weeks=1))\n\n\nclass PerishableProductQuerySet(ProductQuerySet):\n model_name = \"PerishableProduct\"\n\n @query()\n def get_new_products(cls):\n return super().get_new_products.conditions() & models.Q(date_perished__lt=datetime.datetime.now()) \n```\n\nIn this example `get_new_products` will return any `Product` that was created less than a week ago or \n`PerishableProduct` if it was created a week ago and won't perish today.\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/Nerlin/django-polymorphic-queryset", "keywords": "", "license": "", "maintainer": "", "maintainer_email": "", "name": "django-polymorphic-queryset", "package_url": "https://pypi.org/project/django-polymorphic-queryset/", "platform": "", "project_url": "https://pypi.org/project/django-polymorphic-queryset/", "project_urls": { "Homepage": "https://github.com/Nerlin/django-polymorphic-queryset" }, "release_url": "https://pypi.org/project/django-polymorphic-queryset/0.2.1/", "requires_dist": [ "Django (>=1.9)" ], "requires_python": "", "summary": "Polymorphic inheritance for Django QuerySet", "version": "0.2.1" }, "last_serial": 4113421, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "5cf0baf8331bd20572bea5d233abeab6", "sha256": "7459d2007563e5494ab0dbc3934372d10acf671c3b46862c50f9e5153f27ee52" }, "downloads": -1, "filename": "django_polymorphic_queryset-0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5cf0baf8331bd20572bea5d233abeab6", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 6546, "upload_time": "2018-07-29T01:49:48", "url": "https://files.pythonhosted.org/packages/18/f7/d09b2d85f55f087b69b1d09f554ea69c0a24aae5782694f156408c28feb8/django_polymorphic_queryset-0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "254bcd286d671e1bee5e1806d2f56dbc", "sha256": "206eccaaf6c2ee6bd14faca780ff4af56fa7b81d89e16cadef4922bb2f24b76f" }, "downloads": -1, "filename": "django-polymorphic-queryset-0.1.tar.gz", "has_sig": false, "md5_digest": "254bcd286d671e1bee5e1806d2f56dbc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5274, "upload_time": "2018-07-29T01:49:49", "url": "https://files.pythonhosted.org/packages/14/b6/8642750adb9e49ec747b5667430825a7e48d75d9f644c57b8403b3d76ac5/django-polymorphic-queryset-0.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "c07bcb0e4ee35a6f0b49ed3c2adbf1a1", "sha256": "5e29f6e42e2a8791e319f0aedfca001ba34300e516853d86a3fb8deef9ca35ba" }, "downloads": -1, "filename": "django_polymorphic_queryset-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "c07bcb0e4ee35a6f0b49ed3c2adbf1a1", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7017, "upload_time": "2018-07-29T10:54:51", "url": "https://files.pythonhosted.org/packages/24/97/da07c59dba2d6df33c7b3735b7e8c94127a1974cb820331458620fa49377/django_polymorphic_queryset-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "35f43b9b319cfb865553bd340f1d9c9c", "sha256": "e6aad75342b47a6d21fb0950ff9bf14dd23c8cfc8523827ecf69a15adc50d2bd" }, "downloads": -1, "filename": "django-polymorphic-queryset-0.2.tar.gz", "has_sig": false, "md5_digest": "35f43b9b319cfb865553bd340f1d9c9c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5735, "upload_time": "2018-07-29T10:54:53", "url": "https://files.pythonhosted.org/packages/2d/31/7d1bee1b490b45440356675fe4f9030a4dce3368809b6d779caae3f7e592/django-polymorphic-queryset-0.2.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "632ee60f26d3ea8fa54c036d2b3f8f37", "sha256": "3ba110625737f6b6ab3bea758ba7513d80ba3231523b362d0553e322fe4096b2" }, "downloads": -1, "filename": "django_polymorphic_queryset-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "632ee60f26d3ea8fa54c036d2b3f8f37", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7087, "upload_time": "2018-07-29T11:01:51", "url": "https://files.pythonhosted.org/packages/05/f7/13d6f236fa38afa61199d5c1d25d8e8cf709f9225aab28ea247c48167a98/django_polymorphic_queryset-0.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4f2fd4a0cc8a86ab9f7f395862b84307", "sha256": "dc3075cd8a8309d55c207cba8b887e84c5baf75d11992c7c0d216bfa4a5e8748" }, "downloads": -1, "filename": "django-polymorphic-queryset-0.2.1.tar.gz", "has_sig": false, "md5_digest": "4f2fd4a0cc8a86ab9f7f395862b84307", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5781, "upload_time": "2018-07-29T11:01:52", "url": "https://files.pythonhosted.org/packages/6c/70/adc3f1fdabc2658fb1e73c1cca8a1a13415fc539cf76ce7cf30f565b93ff/django-polymorphic-queryset-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "632ee60f26d3ea8fa54c036d2b3f8f37", "sha256": "3ba110625737f6b6ab3bea758ba7513d80ba3231523b362d0553e322fe4096b2" }, "downloads": -1, "filename": "django_polymorphic_queryset-0.2.1-py3-none-any.whl", "has_sig": false, "md5_digest": "632ee60f26d3ea8fa54c036d2b3f8f37", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7087, "upload_time": "2018-07-29T11:01:51", "url": "https://files.pythonhosted.org/packages/05/f7/13d6f236fa38afa61199d5c1d25d8e8cf709f9225aab28ea247c48167a98/django_polymorphic_queryset-0.2.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4f2fd4a0cc8a86ab9f7f395862b84307", "sha256": "dc3075cd8a8309d55c207cba8b887e84c5baf75d11992c7c0d216bfa4a5e8748" }, "downloads": -1, "filename": "django-polymorphic-queryset-0.2.1.tar.gz", "has_sig": false, "md5_digest": "4f2fd4a0cc8a86ab9f7f395862b84307", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 5781, "upload_time": "2018-07-29T11:01:52", "url": "https://files.pythonhosted.org/packages/6c/70/adc3f1fdabc2658fb1e73c1cca8a1a13415fc539cf76ce7cf30f565b93ff/django-polymorphic-queryset-0.2.1.tar.gz" } ] }