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.5.tar.gz (13.8 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.5-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nexusrepo-0.2.5.tar.gz
  • Upload date:
  • Size: 13.8 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.5.tar.gz
Algorithm Hash digest
SHA256 d8220c953e678a6ade9cb3049a865b18d54a482808f4ccb157db5e1a33e4300e
MD5 91e0c7d84842dd70046a345010d5cc23
BLAKE2b-256 8daae540282f15fd849ccacf32e28b47d51a323050772be2eab973c3a5502629

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nexusrepo-0.2.5-py3-none-any.whl
  • Upload date:
  • Size: 17.9 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.5-py3-none-any.whl
Algorithm Hash digest
SHA256 4273895fb36537deff9d16cec7ad3ab08ad49d491b5ebb923941e414ae78c137
MD5 cac3306c62f0a342091cb5a7eacb15f0
BLAKE2b-256 936563a2b1146892cf4bd1cb33c2716dd311d396836c20be127e576178837dd3

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