Skip to content

Commit

Permalink
add
Browse files Browse the repository at this point in the history
  • Loading branch information
baseplate-admin committed Feb 24, 2024
1 parent 4e1c5dd commit cff4a2d
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 21 deletions.
23 changes: 13 additions & 10 deletions django_ltree/managers.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
from django.db import models

from typing import TYPE_CHECKING
from django_ltree.paths import PathGenerator

from .querysets import TreeQuerySet

class TreeQuerySet(models.QuerySet):
def roots(self):
return self.filter(path__depth=1)

def children(self, path):
return self.filter(path__descendants=path, path__depth=len(path) + 1)
if TYPE_CHECKING:
from django_ltree.models import TreeModel


class TreeManager(models.Manager):
def get_queryset(self):
"""Returns a queryset with the models ordered by `path`"""
return TreeQuerySet(model=self.model, using=self._db).order_by("path")

def roots(self):
def roots(self) -> models.QuerySet["TreeModel"]:
"""Returns the roots of a given model"""
return self.filter().roots()

def children(self, path):
def children(self, path: str) -> models.QuerySet["TreeModel"]:
"""Returns the childrens of a given object"""
return self.filter().children(path)

def create_child(self, parent=None, **kwargs):
def create_child(
self, parent: "TreeModel" = None, **kwargs
) -> models.QuerySet["TreeModel"]:
"""Creates a tree child with or without parent"""
paths_in_use = parent.children() if parent else self.roots()
prefix = parent.path if parent else None
path_generator = PathGenerator(
Expand Down
14 changes: 14 additions & 0 deletions django_ltree/querysets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.db import models

from typing import TYPE_CHECKING

if TYPE_CHECKING:
from .models import TreeModel


class TreeQuerySet(models.QuerySet):
def roots(self) -> models.QuerySet["TreeModel"]:
return self.filter(path__depth=1)

def children(self, path: str) -> models.QuerySet["TreeModel"]:
return self.filter(path__descendants=path, path__depth=len(path) + 1)
26 changes: 17 additions & 9 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,31 @@
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information

project = 'django_ltree'
copyright = '2024, baseplate-admin'
author = 'baseplate-admin'
release = '0.1.5'
project = "django_ltree"
copyright = "2024, baseplate-admin"
author = "baseplate-admin"
release = "0.1.5"

# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = []
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.viewcode",
]

templates_path = ['_templates']
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
templates_path = ["_templates"]
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.


autodoc_typehints = "description"

# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output

html_theme = 'alabaster'
html_static_path = ['_static']
html_theme = "furo"
html_static_path = ["_static"]
6 changes: 5 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
Welcome to django_ltree's documentation!
========================================

Augmenting `django` orm with postgres `ltree <https://www.postgresql.org/docs/current/ltree.html>`_ functionalities

.. toctree::
:maxdepth: 2
:caption: Contents:


installation
usage
manager

Indices and tables
==================
Expand Down
35 changes: 35 additions & 0 deletions docs/installation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
Installation
============

Requirements
------------

Python 3.10 to 3.12 supported.

Django 4.2 to 5.0 supported.


Installation
------------

1. Install with **pip**:

.. code-block:: sh
python -m pip install django-ltree-2
2. Add django-ltree to your ``INSTALLED_APPS``:

.. code-block:: python
INSTALLED_APPS = [
...,
"django_ltree",
...,
]
3. Run migrations:

.. code-block:: sh
./manage.py migrate
17 changes: 17 additions & 0 deletions docs/manager.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Manager
=======


.. currentmodule:: django_ltree.managers

.. class:: TreeManager

This manager augments the django model, allowing it to be queried with tree specific queries

.. automethod:: get_queryset

.. automethod:: roots

.. automethod:: children

.. automethod:: create_child
78 changes: 78 additions & 0 deletions docs/usage.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
Usage
=====

Lets assume that our model looks like this.

.. code-block:: python
# models.py
from django import models
from django_ltree import TreeModel
class CustomTree(TreeModel):
text = models.TextField()
Create a child without parent
-----------------------------

.. code-block:: python
from .models import CustomTree
CustomTree.objects.create_child(text='Hello world')
The following code with create a child with no parent (ie:roots of a tree)

Create a child with parent
--------------------------
Let's assume we want to add a child to the CustomTree object of `pk 1`

.. code-block:: python
from .models import CustomTree
# This must return a single object
parent: CustomTree = CustomTree.objects.get(pk=1)
CustomTree.objects.create_child(text='Hello world', parent=parent)
Get all the roots of the model
------------------------------
A root means the the object that childrens anchor to.

.. code-block:: python
from .models import CustomTree
roots: list[CustomTree] = CustomTree.objects.roots()
Get all the childrens of a object
---------------------------------
To get the childrens of a object, we can first get the object then call the QuerySet specific children function.

.. code-block:: python
from .models import CustomTree
instance = CustomTree.objects.get(pk=1)
childrens: list[CustomTree] = instance.children()
Get the length of childrens of a object
---------------------------------------
`django` specific database functions still work when we call the filter method.

Lets assume we want to get the childrens of `CustomTree` object whose pk is 1.

.. code-block:: python
from .models import CustomTree
instance = CustomTree.objects.get(pk=1)
childrens: int = instance.children().count()
62 changes: 61 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ pytest-django = "^4.8.0"
sphinx = "^7.2.6"
furo = "^2024.1.29"
myst-parser = "^2.0.0"
sphinx-reload = "^0.2.0"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit cff4a2d

Please sign in to comment.