Skip to main content

NexusData - data access, services and DTO abstractions.

Project description

NexusRepo

NexusData is a Python data access library that provides a Spring Data JPA–inspired repository pattern on top of SQLAlchemy, with first-class compatibility for SQLModel.

It enables developers to define repositories using declarative method names, custom queries, and DTO projections, while keeping full access to SQLAlchemy’s power.

✨ Key Features

  • Repository Abstraction inspired by Spring Data JPA
  • SQL Alchemy core & ORM support
  • SQLModel compactible
  • Method-name–based query generation
  • DTO / Projection queries
  • Transaction Management

Installation

pip install nexusrepo

Demonstration

Let's create a simple crud to learn how to use NexusRepo

Creating Models

from sqlmodel import SQLModel, Field, Relationship
from typing import Optional


class Category(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    name: str = Field(nullable=False)


class Product(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    name: str = Field(nullable=False)
    price: float = Field(nullable=False)
    category_id: int = Field(foreign_key="category.id")
    category: Category = Relationship()

Creating Repository for each model

from nexusdata.orms.repositories import NexusRepository

class CategoryRepo(NexusRepository[Category, int]):
    pass

class ProductRepo(NexusRepository[Product, int]):
    pass

Using Repository

NexusRepository takes Session as constructor argument

from sqlmodel import Session, create_engine

engine = create_engine("sqlite:///:memory:")
def get_session():
    with Session(engine) as session:
        yield session
session = next(get_session())        

category_repo = CategoryRepo(session)
product_repo = ProductRepo(session)

After initializing repositories, we can just use following methods instantly

save(entity:MODEL) -> MODEL
save_all(entities:list[MODEL]) -> list[MODEL]
find_by_id(id:ID) -> MODEL
count() -> int
delete(entity:MODEL)
delete_by_id(id:ID)

Query Function

NexusRepo supports Spring inspired query method which we can define and use methods without implementing just by following the naming rule.

for example

Let's write a function that find products by name and price range. All you have to do is to add a @query decorator on the function.

from nexusdata.orms.repositories import NexusRepository
from nexusdata.legacy.decorators import query

class ProductRepo(NexusRepository[Product, int]):
    
    @query
    def find_by_name_like_and_price_lte(self, name:str, price:float) -> list[Product]:pass

Query Projection

NexusRepo also supports sql projection too. Never return the whole entity, wrap it in a DTO. To do this, we can use @query decorator again but with sql attribute, user can also pass dto_cls and map_func which accept sqlalchemy's RowMapping and convert to DTO, for better control. important ! Projection columns should reflect the DTO class's constructor argument

for example let's write a function that retrieve category with their product counts

from dataclasses import dataclass
from nexusdata.orms.repositories import NexusRepository
from nexusdata.legacy.decorators import query

@dataclass
class CategoryDto:
    id:int
    name:str
    products:int

    
class CategoryRepo(NexusRepository[Category, int]):
    
    @query(sql="""
        select c.id as id, c.name as name, count(p.id) as products
        from category as c
        left join product as p on p.category_id = c.id
        group by c.id, c.name
    """, dto=CategoryDto)
    def get_all_category_dtos(self) -> list[CategoryDto]:pass

Service

In above example, we introduce NexusService, which is also an element of NexusRepo, that take Session as constructor argument. Point of NexusSession is initializing every repositories inside the service automatically. Therefore, we don't need to create instances for repositories we used in a service. NexusService does it all for you.

Transaction

NexusRepo also support @transactional decorator for transaction management. Remember! In NexusRepo repositories never commit, therefore, you need to add @transactional decorator on methods to persit. Recommended - Do it in service layer

for example

from nexusdata.orms.services import NexusService
from nexusdata.legacy.decorators import transactional

class ProductForm:
    name:str
    price:float

class ProductService(NexusService):
    repo:ProductRepo

    @transactional
    def save(self, form:ProductForm) -> int:
        p:Product = self.save(Product(name=form.name, price=form.price))
        return p.id

    
    @transactional(read_only=True)
    def get_all(self) -> list[CategoryDto]:
        return self.repo.get_all_category_dtos()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nexusrepo-0.2.2.tar.gz (13.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nexusrepo-0.2.2-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

Details for the file nexusrepo-0.2.2.tar.gz.

File metadata

  • Download URL: nexusrepo-0.2.2.tar.gz
  • Upload date:
  • Size: 13.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0rc2

File hashes

Hashes for nexusrepo-0.2.2.tar.gz
Algorithm Hash digest
SHA256 8554d22ce473f92b0039da560b1e706f180890de854dbc30fa2d4c7d26cf097e
MD5 65ae8a4bef9e2e2b0642c7e85dfb702b
BLAKE2b-256 77e1e13e3246921fa61b6ffccdd5fcc076a8aed5c69347994cf583a75c94647e

See more details on using hashes here.

File details

Details for the file nexusrepo-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: nexusrepo-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 17.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0rc2

File hashes

Hashes for nexusrepo-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 1895dffd5d89fa28cf8eae130e1ab5756859e687630f6c6dab08c1c3f3230d4e
MD5 b3593f49e795470e9ff3e5642e63b75d
BLAKE2b-256 9fa052ae51f8af6b1c5383289d519e01c060f41e34c339b6fb078f1a5b81bbdd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page