-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Also, - Add license section - Add note about testing against postgres only - Use README.rst for long description on PyPI
- Loading branch information
Showing
4 changed files
with
115 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -95,3 +95,6 @@ celerybeat-schedule | |
|
||
# dotenv | ||
.env | ||
|
||
# built readme | ||
README.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
************** | ||
Django Include | ||
************** | ||
|
||
ORM extensions for performance-conscious perfectionists. | ||
|
||
Django-include provides `select_related` functionality for Many-to-X relation. | ||
|
||
|
||
Requirements | ||
============ | ||
|
||
Python 2.7 or 3.4+, Django 1.9+, and any SQL server with support for JSON aggregations. | ||
|
||
Currently tested against Postgres. May work with SQLite with the JSON1 extension. | ||
|
||
|
||
Installation | ||
============ | ||
|
||
:: | ||
|
||
pip install django-include | ||
|
||
Usage | ||
===== | ||
|
||
Add `include` to `INSTALLED_APPS`. | ||
|
||
Attach ``IncludeManager`` to a model: | ||
|
||
.. code-block:: python | ||
from include import IncludeMaager | ||
class BlogPost(models.Model): | ||
objects = IncludeManager() | ||
Subclass `IncludeQuerySet`: | ||
|
||
.. code-block:: python | ||
from include import IncludeQuerySet | ||
class BlogPost(models.Model): | ||
objects = CustomQuerySet.as_manager() | ||
What/Why? | ||
========= | ||
|
||
Consider the following: | ||
|
||
Given the following models. | ||
|
||
.. code-block:: python | ||
class Email(Model): | ||
name = CharField() | ||
user = ForeignKey('User') | ||
class User(Model): | ||
emails = ... | ||
class Contributor(Model): | ||
role = CharField() | ||
user = ForeignKey('User') | ||
project = ForeignKey('Project') | ||
class Project(Model): | ||
contributors = ... | ||
There is an endpoint that returns all the users that contributed to a project, their roles, and their email addresses. | ||
|
||
If this endpoint were to be implemented using just Django's ORM, it would end up looking something like this: | ||
|
||
.. code-block:: python | ||
project = Project.objects.get(pk=id) # 1 Query! | ||
for contributor in project.contributors.select_related('users'): # 1 Query! | ||
[x for x in contributor.user.emails.all()] # N * M Queries! | ||
# Some serialization code | ||
At first this solution seems fine, but what happens when a project has an entire college of people, each with a couple email addresses? | ||
Now, there are certainly other tricks that could be done here to reduce the number of queries and runtime. | ||
For instance, dropping down into raw SQL with a couple joins and/or subselects. | ||
|
||
Or you could just use `.include`, do a single query, and not have to explain all the *neat* things you did. | ||
|
||
.. code-block:: python | ||
project = Project.objects.include('contributors__user__emails') # 1 Query! | ||
for contributor in project.contributors.all(): # Already loaded | ||
[x for x in contributor.user.emails.all()] # Already loaded | ||
# Some serialization code | ||
How? | ||
==== | ||
|
||
Django Include abuses JSON aggregations and Django's `extra`/`annotate` functions to embed related data. | ||
|
||
License | ||
======= | ||
|
||
MIT licensed. See the bundled `LICENSE <https://github.com/chrisseto/django-include/blob/master/LICENSE>`_ file for more details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,10 @@ | |
from setuptools import setup | ||
|
||
|
||
# Remove build status and move Gitter link under title for PyPi | ||
# README = open('README.md').read() \ | ||
# .replace('|Build Status|', '', 1) \ | ||
# .replace('|Gitter|', '', 1) \ | ||
# .replace('===\n', '===\n\n|Gitter|\n') | ||
def read(fname): | ||
with open(fname) as fp: | ||
content = fp.read() | ||
return content | ||
|
||
|
||
setup( | ||
|
@@ -16,8 +15,7 @@ | |
author='Chris Seto', | ||
author_email='[email protected]', | ||
description='ORM extensions for performance conscious perfectionists.', | ||
# long_description=README, | ||
long_description='', | ||
long_description=read('README.rst'), | ||
url='http://github.com/chrisseto/django-include', | ||
license='MIT', | ||
packages=[ | ||
|