# django-join-unrelated
![Python version](https://img.shields.io/badge/Python-3.8%2B-blue)
[![Tests](https://github.com/KazakovDenis/django-join-unrelated/actions/workflows/cicd.yml/badge.svg)](https://github.com/KazakovDenis/django-join-unrelated/actions/workflows/cicd.yml)
### Use SQL Join with Django ORM models having no relations.
If you have models in your project that share the same data but have no relations,
you might face a situation when you need to join them. But Django does not provide
this functionality yet.
With `django-join-unrelated` you can do the following
(models defined [here](https://github.com/KazakovDenis/django-join-unrelated/blob/main/app/core/models.py)):
```python
from app.core.models import Jedi, Person
Person.objects.create(first_name='Padme', last_name='Amidala', birth_place='Naboo')
Person.objects.create(first_name='Obi-Wan', last_name='Kenobi', birth_place='Stewjon')
Jedi.objects.create(first_name='Obi-Wan', last_name='Kenobi', force=100)
Jedi.objects.create(first_name='Mace', last_name='Windu', force=80)
Jedi.objects.join(first_name=Person.first_name).values_list('first_name')
# <UnrelatedJoinQuerySet [('Obi-Wan',)]>
print(Jedi.objects.join(first_name=Person.first_name).values_list('first_name').query)
# SELECT "core_jedi"."first_name" FROM "core_jedi" INNER JOIN core_person ON ("core_jedi"."first_name" = core_person."first_name")
# Set join type explicitly
from django_join_unrelated import JoinType
Jedi.objects.join(first_name=Person.first_name, join_type=JoinType.FULL)
# Join on multiple fields
Jedi.objects.join(first_name=Person.first_name, last_name=Person.last_name)
# Join multiple models
Jedi.objects.join(first_name=Person.first_name, id=User.id)
```
`django-join-unrelated` tries to keep all QuerySet power where it is possible:
```python
Jedi.objects.join(first_name=Person.first_name).filter(last_name='Kenobi')
# <UnrelatedJoinQuerySet [<Jedi: Obi-Wan Kenobi>]>
Jedi.objects.join(first_name=Person.first_name).annotate(name=F('first_name'))[0].name
# 'Obi-Wan'
Jedi.objects.join(first_name=Person.first_name).aggregate(Sum('force'))
# {'force__sum': 100}
```
## Installation
You can install `django-join-unrelated` using pip:
```
pip install django-join-unrelated
```
## Usage
Just import `UnrelatedJoinManager` and set it as an attribute to your models:
```python
from django.db import models
from django_join_unrelated import UnrelatedJoinManager
class Jedi(models.Model):
first_name = models.CharField('First name', max_length=128)
last_name = models.CharField('Last name', max_length=128)
force = models.IntegerField('Force')
objects = UnrelatedJoinManager()
class Meta:
verbose_name = 'Jedi'
```
**Already implemented:**
- filtering via joins
**Not implemented yet but planned:**
- unrelated objects selection
- return of joined values
Raw data
{
"_id": null,
"home_page": "https://pypi.org/project/django-join-unrelated",
"name": "django-join-unrelated",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.8,<4.0",
"maintainer_email": "",
"keywords": "django,django-orm,orm",
"author": "Denis Kazakov",
"author_email": "denis@kazakov.ru.net",
"download_url": "https://files.pythonhosted.org/packages/e7/71/a570880ea4161adc360447a9523fb1a7d91371aaa3c593dfa159d2d21a1a/django-join-unrelated-0.2.0.tar.gz",
"platform": null,
"description": "# django-join-unrelated\n![Python version](https://img.shields.io/badge/Python-3.8%2B-blue)\n[![Tests](https://github.com/KazakovDenis/django-join-unrelated/actions/workflows/cicd.yml/badge.svg)](https://github.com/KazakovDenis/django-join-unrelated/actions/workflows/cicd.yml)\n\n### Use SQL Join with Django ORM models having no relations.\n\nIf you have models in your project that share the same data but have no relations, \nyou might face a situation when you need to join them. But Django does not provide \nthis functionality yet.\n \nWith `django-join-unrelated` you can do the following \n(models defined [here](https://github.com/KazakovDenis/django-join-unrelated/blob/main/app/core/models.py)):\n```python\nfrom app.core.models import Jedi, Person\n\nPerson.objects.create(first_name='Padme', last_name='Amidala', birth_place='Naboo')\nPerson.objects.create(first_name='Obi-Wan', last_name='Kenobi', birth_place='Stewjon')\nJedi.objects.create(first_name='Obi-Wan', last_name='Kenobi', force=100)\nJedi.objects.create(first_name='Mace', last_name='Windu', force=80)\n\nJedi.objects.join(first_name=Person.first_name).values_list('first_name')\n# <UnrelatedJoinQuerySet [('Obi-Wan',)]>\n\nprint(Jedi.objects.join(first_name=Person.first_name).values_list('first_name').query)\n# SELECT \"core_jedi\".\"first_name\" FROM \"core_jedi\" INNER JOIN core_person ON (\"core_jedi\".\"first_name\" = core_person.\"first_name\")\n\n# Set join type explicitly\nfrom django_join_unrelated import JoinType\n\nJedi.objects.join(first_name=Person.first_name, join_type=JoinType.FULL)\n\n# Join on multiple fields\nJedi.objects.join(first_name=Person.first_name, last_name=Person.last_name)\n\n# Join multiple models\nJedi.objects.join(first_name=Person.first_name, id=User.id)\n```\n\n`django-join-unrelated` tries to keep all QuerySet power where it is possible:\n```python\nJedi.objects.join(first_name=Person.first_name).filter(last_name='Kenobi')\n# <UnrelatedJoinQuerySet [<Jedi: Obi-Wan Kenobi>]>\n\nJedi.objects.join(first_name=Person.first_name).annotate(name=F('first_name'))[0].name\n# 'Obi-Wan'\n\nJedi.objects.join(first_name=Person.first_name).aggregate(Sum('force'))\n# {'force__sum': 100}\n```\n\n## Installation\nYou can install `django-join-unrelated` using pip:\n\n```\npip install django-join-unrelated\n```\n\n## Usage\nJust import `UnrelatedJoinManager` and set it as an attribute to your models:\n\n```python\nfrom django.db import models\nfrom django_join_unrelated import UnrelatedJoinManager\n\nclass Jedi(models.Model):\n first_name = models.CharField('First name', max_length=128)\n last_name = models.CharField('Last name', max_length=128)\n force = models.IntegerField('Force')\n\n objects = UnrelatedJoinManager()\n\n class Meta:\n verbose_name = 'Jedi'\n```\n \n**Already implemented:**\n- filtering via joins\n\n**Not implemented yet but planned:**\n- unrelated objects selection\n- return of joined values\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Use SQL Join with Django ORM models having no relations.",
"version": "0.2.0",
"project_urls": {
"Homepage": "https://pypi.org/project/django-join-unrelated",
"Repository": "https://github.com/KazakovDenis/django-join-unrelated"
},
"split_keywords": [
"django",
"django-orm",
"orm"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8064589a8b5e3caed840ad723c1699279088817915229ec00aa5af571f917520",
"md5": "cb2dde2b8fbaedd24d7f275b623e6770",
"sha256": "fe0b23e246ebdb700eae03b8f22c83da877ea501fcb205ba5fc06b09b2448b85"
},
"downloads": -1,
"filename": "django_join_unrelated-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cb2dde2b8fbaedd24d7f275b623e6770",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8,<4.0",
"size": 5557,
"upload_time": "2023-06-11T20:39:19",
"upload_time_iso_8601": "2023-06-11T20:39:19.975460Z",
"url": "https://files.pythonhosted.org/packages/80/64/589a8b5e3caed840ad723c1699279088817915229ec00aa5af571f917520/django_join_unrelated-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e771a570880ea4161adc360447a9523fb1a7d91371aaa3c593dfa159d2d21a1a",
"md5": "dec00a4d41561804b6461cb38af1db07",
"sha256": "434b611d9fa1163711a47861c289de7c6c5f27aa1299d52ef94111085a75c710"
},
"downloads": -1,
"filename": "django-join-unrelated-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "dec00a4d41561804b6461cb38af1db07",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8,<4.0",
"size": 5464,
"upload_time": "2023-06-11T20:39:18",
"upload_time_iso_8601": "2023-06-11T20:39:18.228742Z",
"url": "https://files.pythonhosted.org/packages/e7/71/a570880ea4161adc360447a9523fb1a7d91371aaa3c593dfa159d2d21a1a/django-join-unrelated-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-11 20:39:18",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "KazakovDenis",
"github_project": "django-join-unrelated",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "django-join-unrelated"
}