Metadata-Version: 2.1
Name: leo-optimizer
Version: 0.0.4
Summary: Package for on fly optimizing SQL queries generated by Django ORM. This package targets the N+1 problem so well known to Django.
Home-page: https://github.com/leopharma/leo-optimizer
License: Apache-2.0
Keywords: graphql,graphene,django,N+1,optimizer
Author: Martin Andersen
Author-email: zdtdk@leo-pharma.com
Maintainer: Martin Andersen
Maintainer-email: zdtdk@leo-pharma.com
Requires-Python: >=3.6,<4.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: Implementation :: PyPy
Classifier: Topic :: Software Development :: Libraries
Requires-Dist: stringcase (>=1.2.0,<2.0.0)
Project-URL: Documentation, https://github.com/leopharma/leo-optimizer
Project-URL: Repository, https://github.com/leopharma/leo-optimizer
Description-Content-Type: text/markdown

# Leo Optimizer

This Django plugin allows you to optimize SQL queries and solve [N+1](https://scoutapm.com/blog/django-and-the-n1-queries-problem) bottleneck for queries resolved in GraphQL, as well as in admin pages.

# Install

```bash
pip install leo-optimizer
```

# Context

Let's say that the business context that you are modeling is around the concept of a city. You modeled your solution following way:

* City has one mayor
* City has many districts
* City belong to one state
* State is in the country
* Country is located in a continent

Outcome of these relations allows you to build a complex GraphQL query that might look like this.

```
query CityQuery {
  allCities{
    mayor {
      city {
        name
      }
    }
    state {
      country {
        continent {
          name
        }
      }
    }
    district {
      city {
        mayor {
          city {
            district {
              name
            }
          }
        }
      }
    }
  }
}
```

# Problem

The problem is that if you didn't use [select_related](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#select-related) and [prefetch_related](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#prefetch-related) on the model that you are resolving then by default you will get [N+1](https://scoutapm.com/blog/django-and-the-n1-queries-problem) problem.


# Solution

You can fix this problem by importing `gql_optimizer` function from `leo_optimizer` package.

In your GraphQL resolver, wrap your model along with FiledNode that you would like to resolve against and return Django QuerySet. Your code should look like the code below.

```python
from leo_optimizer import gql_optimizer

from app.models import City

def resolve_all_city(self, info):
    queryset = gql_optimizer(City.objects.all(), info.field_nodes[0])
    return queryset
```

# Admin

Automatically generated django admin pages suffer from the same [N+1](https://scoutapm.com/blog/django-and-the-n1-queries-problem) problem. To solve slow loading admin pages you can import `QuickAdmin` class in your `admin.py` file as shown on the example below.


```python
from django.apps import apps
from django.contrib import admin

from leo_optimizer import QuickAdmin


for model in apps.get_app_config("name_of_your_application").get_models():
    admin.site.register(model, QuickAdmin)
```
