django-datalog


Namedjango-datalog JSON
Version 0.3.1 PyPI version JSON
download
home_pageNone
SummaryDjango Datalog - Logic programming and inference engine for Django applications
upload_time2025-07-23 18:21:57
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseNone
keywords datalog django facts inference-engine logic-programming query rules
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # django-datalog

A logic programming and inference engine for Django applications.

## Installation

```bash
pip install django-datalog
```

```python
# settings.py
INSTALLED_APPS = ['django_datalog']
```

```bash
python manage.py migrate
```

## Core Concepts

### Facts
Define facts as Python classes with Django model integration:

```python
from django_datalog.models import Fact, Var

class WorksFor(Fact):
    subject: Employee | Var  # Employee
    object: Company | Var    # Company

class ColleaguesOf(Fact, inferred=True):  # Inferred facts can't be stored directly
    subject: Employee | Var
    object: Employee | Var
```

### Rules
Define inference logic with tuples (AND) and lists (OR):

```python
from django_datalog.rules import rule

# Simple rule: Colleagues work at same company
rule(
    ColleaguesOf(Var("emp1"), Var("emp2")),
    WorksFor(Var("emp1"), Var("company")) & WorksFor(Var("emp2"), Var("company"))
)

# Disjunctive rule: HasAccess via admin OR manager
rule(
    HasAccess(Var("user"), Var("resource")),
    IsAdmin(Var("user")) | IsManager(Var("user"), Var("resource"))
)

# Mixed rule: Complex access control
rule(
    CanEdit(Var("user"), Var("doc")),
    IsOwner(Var("user"), Var("doc")) | 
    (IsManager(Var("user"), Var("folder")) & Contains(Var("folder"), Var("doc")))
)
```

### Fact Operators
Use `|` (OR) and `&` (AND) operators:

```python
# Modern operator syntax (recommended):
rule(head, fact1 | fact2)           # OR: fact1 OR fact2
rule(head, fact1 & fact2)           # AND: fact1 AND fact2

# Combining operators:
rule(head, (fact1 & fact2) | fact3)  # (fact1 AND fact2) OR fact3
rule(head, fact1 & fact2 & fact3)    # fact1 AND fact2 AND fact3
rule(head, fact1 | fact2 | fact3)    # fact1 OR fact2 OR fact3

# Legacy syntax (still supported):
rule(head, [fact1, fact2])           # OR (list syntax)
rule(head, (fact1, fact2))          # AND (tuple syntax)
```

### Storing Facts
```python
from django_datalog.models import store_facts

store_facts(
    WorksFor(subject=alice, object=tech_corp),
    WorksFor(subject=bob, object=tech_corp),
)
```

### Querying
```python
from django_datalog.models import query

# Find Alice's colleagues
colleagues = list(query(ColleaguesOf(alice, Var("colleague"))))

# With Django Q constraints
managers = list(query(WorksFor(Var("emp", where=Q(is_manager=True)), tech_corp)))

# Complex queries
results = list(query(
    ColleaguesOf(Var("emp1"), Var("emp2")),
    WorksFor(Var("emp1"), Var("company", where=Q(is_active=True)))
))
```

### Rule Context
Isolate rules for testing or temporary logic:

```python
from django_datalog.models import rule_context

# As context manager
with rule_context():
    rule(TestFact(Var("x")), LocalFact(Var("x")))
    results = query(TestFact(Var("x")))  # Rules active here

# As decorator
@rule_context
def test_something(self):
    rule(TestFact(Var("x")), LocalFact(Var("x")))
    assert len(query(TestFact(Var("x")))) > 0
```

### Variables & Constraints
```python
# Basic variable
emp = Var("employee")

# With Django Q constraints
senior_emp = Var("employee", where=Q(years_experience__gte=5))

# Multiple constraints
constrained = Var("emp", where=Q(is_active=True) & Q(department="Engineering"))
```

## Performance Features

### Automatic Optimization
The engine automatically:
- Propagates constraints across same-named variables
- Orders execution by selectivity (most selective first)
- Learns from execution times for better planning
- Pushes constraints to the database

```python
# You write natural queries:
query(
    ColleaguesOf(Var("emp1"), Var("emp2", where=Q(department="Engineering"))),
    WorksFor(Var("emp1"), Var("company", where=Q(is_active=True)))
)

# Engine automatically optimizes constraint propagation and execution order
```

## Example: Complete Employee System

```python
# models.py
class Employee(models.Model):
    name = models.CharField(max_length=100)
    is_manager = models.BooleanField(default=False)

class WorksFor(Fact):
    subject: Employee | Var
    object: Company | Var

class ColleaguesOf(Fact, inferred=True):
    subject: Employee | Var
    object: Employee | Var

# rules.py
rule(
    ColleaguesOf(Var("emp1"), Var("emp2")),
    WorksFor(Var("emp1"), Var("company")) & WorksFor(Var("emp2"), Var("company"))
)

# usage.py
store_facts(
    WorksFor(subject=alice, object=tech_corp),
    WorksFor(subject=bob, object=tech_corp),
)

# Query automatically infers colleagues
colleagues = query(ColleaguesOf(alice, Var("colleague")))
```

## Testing

```python
class MyTest(TestCase):
    @rule_context  # Isolate rules per test
    def test_access_control(self):
        rule(CanAccess(Var("user")), IsAdmin(Var("user")))
        
        results = query(CanAccess(admin_user))
        self.assertEqual(len(results), 1)
```

## Requirements

- Python 3.10+
- Django 5.0+

## License

MIT License

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-datalog",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "datalog, django, facts, inference-engine, logic-programming, query, rules",
    "author": null,
    "author_email": "Eddy Ernesto del Valle Pino <eddy@edelvalle.me>",
    "download_url": "https://files.pythonhosted.org/packages/71/67/99afd71240e20bf94c7170976e3fecfb968461e345f5e27059acf5c28d85/django_datalog-0.3.1.tar.gz",
    "platform": null,
    "description": "# django-datalog\n\nA logic programming and inference engine for Django applications.\n\n## Installation\n\n```bash\npip install django-datalog\n```\n\n```python\n# settings.py\nINSTALLED_APPS = ['django_datalog']\n```\n\n```bash\npython manage.py migrate\n```\n\n## Core Concepts\n\n### Facts\nDefine facts as Python classes with Django model integration:\n\n```python\nfrom django_datalog.models import Fact, Var\n\nclass WorksFor(Fact):\n    subject: Employee | Var  # Employee\n    object: Company | Var    # Company\n\nclass ColleaguesOf(Fact, inferred=True):  # Inferred facts can't be stored directly\n    subject: Employee | Var\n    object: Employee | Var\n```\n\n### Rules\nDefine inference logic with tuples (AND) and lists (OR):\n\n```python\nfrom django_datalog.rules import rule\n\n# Simple rule: Colleagues work at same company\nrule(\n    ColleaguesOf(Var(\"emp1\"), Var(\"emp2\")),\n    WorksFor(Var(\"emp1\"), Var(\"company\")) & WorksFor(Var(\"emp2\"), Var(\"company\"))\n)\n\n# Disjunctive rule: HasAccess via admin OR manager\nrule(\n    HasAccess(Var(\"user\"), Var(\"resource\")),\n    IsAdmin(Var(\"user\")) | IsManager(Var(\"user\"), Var(\"resource\"))\n)\n\n# Mixed rule: Complex access control\nrule(\n    CanEdit(Var(\"user\"), Var(\"doc\")),\n    IsOwner(Var(\"user\"), Var(\"doc\")) | \n    (IsManager(Var(\"user\"), Var(\"folder\")) & Contains(Var(\"folder\"), Var(\"doc\")))\n)\n```\n\n### Fact Operators\nUse `|` (OR) and `&` (AND) operators:\n\n```python\n# Modern operator syntax (recommended):\nrule(head, fact1 | fact2)           # OR: fact1 OR fact2\nrule(head, fact1 & fact2)           # AND: fact1 AND fact2\n\n# Combining operators:\nrule(head, (fact1 & fact2) | fact3)  # (fact1 AND fact2) OR fact3\nrule(head, fact1 & fact2 & fact3)    # fact1 AND fact2 AND fact3\nrule(head, fact1 | fact2 | fact3)    # fact1 OR fact2 OR fact3\n\n# Legacy syntax (still supported):\nrule(head, [fact1, fact2])           # OR (list syntax)\nrule(head, (fact1, fact2))          # AND (tuple syntax)\n```\n\n### Storing Facts\n```python\nfrom django_datalog.models import store_facts\n\nstore_facts(\n    WorksFor(subject=alice, object=tech_corp),\n    WorksFor(subject=bob, object=tech_corp),\n)\n```\n\n### Querying\n```python\nfrom django_datalog.models import query\n\n# Find Alice's colleagues\ncolleagues = list(query(ColleaguesOf(alice, Var(\"colleague\"))))\n\n# With Django Q constraints\nmanagers = list(query(WorksFor(Var(\"emp\", where=Q(is_manager=True)), tech_corp)))\n\n# Complex queries\nresults = list(query(\n    ColleaguesOf(Var(\"emp1\"), Var(\"emp2\")),\n    WorksFor(Var(\"emp1\"), Var(\"company\", where=Q(is_active=True)))\n))\n```\n\n### Rule Context\nIsolate rules for testing or temporary logic:\n\n```python\nfrom django_datalog.models import rule_context\n\n# As context manager\nwith rule_context():\n    rule(TestFact(Var(\"x\")), LocalFact(Var(\"x\")))\n    results = query(TestFact(Var(\"x\")))  # Rules active here\n\n# As decorator\n@rule_context\ndef test_something(self):\n    rule(TestFact(Var(\"x\")), LocalFact(Var(\"x\")))\n    assert len(query(TestFact(Var(\"x\")))) > 0\n```\n\n### Variables & Constraints\n```python\n# Basic variable\nemp = Var(\"employee\")\n\n# With Django Q constraints\nsenior_emp = Var(\"employee\", where=Q(years_experience__gte=5))\n\n# Multiple constraints\nconstrained = Var(\"emp\", where=Q(is_active=True) & Q(department=\"Engineering\"))\n```\n\n## Performance Features\n\n### Automatic Optimization\nThe engine automatically:\n- Propagates constraints across same-named variables\n- Orders execution by selectivity (most selective first)\n- Learns from execution times for better planning\n- Pushes constraints to the database\n\n```python\n# You write natural queries:\nquery(\n    ColleaguesOf(Var(\"emp1\"), Var(\"emp2\", where=Q(department=\"Engineering\"))),\n    WorksFor(Var(\"emp1\"), Var(\"company\", where=Q(is_active=True)))\n)\n\n# Engine automatically optimizes constraint propagation and execution order\n```\n\n## Example: Complete Employee System\n\n```python\n# models.py\nclass Employee(models.Model):\n    name = models.CharField(max_length=100)\n    is_manager = models.BooleanField(default=False)\n\nclass WorksFor(Fact):\n    subject: Employee | Var\n    object: Company | Var\n\nclass ColleaguesOf(Fact, inferred=True):\n    subject: Employee | Var\n    object: Employee | Var\n\n# rules.py\nrule(\n    ColleaguesOf(Var(\"emp1\"), Var(\"emp2\")),\n    WorksFor(Var(\"emp1\"), Var(\"company\")) & WorksFor(Var(\"emp2\"), Var(\"company\"))\n)\n\n# usage.py\nstore_facts(\n    WorksFor(subject=alice, object=tech_corp),\n    WorksFor(subject=bob, object=tech_corp),\n)\n\n# Query automatically infers colleagues\ncolleagues = query(ColleaguesOf(alice, Var(\"colleague\")))\n```\n\n## Testing\n\n```python\nclass MyTest(TestCase):\n    @rule_context  # Isolate rules per test\n    def test_access_control(self):\n        rule(CanAccess(Var(\"user\")), IsAdmin(Var(\"user\")))\n        \n        results = query(CanAccess(admin_user))\n        self.assertEqual(len(results), 1)\n```\n\n## Requirements\n\n- Python 3.10+\n- Django 5.0+\n\n## License\n\nMIT License\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Django Datalog - Logic programming and inference engine for Django applications",
    "version": "0.3.1",
    "project_urls": {
        "Changelog": "https://github.com/edelvalle/django-datalog/blob/main/CHANGELOG.md",
        "Documentation": "https://django-datalog.readthedocs.io/",
        "Homepage": "https://github.com/edelvalle/django-datalog",
        "Issues": "https://github.com/edelvalle/django-datalog/issues",
        "Repository": "https://github.com/edelvalle/django-datalog.git"
    },
    "split_keywords": [
        "datalog",
        " django",
        " facts",
        " inference-engine",
        " logic-programming",
        " query",
        " rules"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "4239bbab5a2d526c5553c72f853df669d23e31a4951c7fbbd8471a22f97a30da",
                "md5": "59096b2ceb43672727182c0b48c2ad0e",
                "sha256": "c35a639af05ed907e7b017f53b1bd8b48f5c4639026953701d4a7cd2b9fc6c9e"
            },
            "downloads": -1,
            "filename": "django_datalog-0.3.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "59096b2ceb43672727182c0b48c2ad0e",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 23101,
            "upload_time": "2025-07-23T18:21:56",
            "upload_time_iso_8601": "2025-07-23T18:21:56.023504Z",
            "url": "https://files.pythonhosted.org/packages/42/39/bbab5a2d526c5553c72f853df669d23e31a4951c7fbbd8471a22f97a30da/django_datalog-0.3.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "716799afd71240e20bf94c7170976e3fecfb968461e345f5e27059acf5c28d85",
                "md5": "f2e05d833238bc03708a48e73f20caf8",
                "sha256": "00150f0d193092acd2155e5a0d3fd84caa23eda931a91fdbbf8cffef6edc049c"
            },
            "downloads": -1,
            "filename": "django_datalog-0.3.1.tar.gz",
            "has_sig": false,
            "md5_digest": "f2e05d833238bc03708a48e73f20caf8",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 23868,
            "upload_time": "2025-07-23T18:21:57",
            "upload_time_iso_8601": "2025-07-23T18:21:57.822440Z",
            "url": "https://files.pythonhosted.org/packages/71/67/99afd71240e20bf94c7170976e3fecfb968461e345f5e27059acf5c28d85/django_datalog-0.3.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-23 18:21:57",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "edelvalle",
    "github_project": "django-datalog",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "django-datalog"
}
        
Elapsed time: 0.52422s