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.0.tar.gz (13.6 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.0-py3-none-any.whl (17.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: nexusrepo-0.2.0.tar.gz
  • Upload date:
  • Size: 13.6 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.0.tar.gz
Algorithm Hash digest
SHA256 8e79dc0bd3afa0dd9243cf058d7307a2131d530f5d6fdc7bcfc99f01118befd8
MD5 a57d48ca64a9c26d87ea28094a237f96
BLAKE2b-256 ebb809354d17139deb37f669eea3312af269d88a451d92b4fda3b7adb9888720

See more details on using hashes here.

File details

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

File metadata

  • Download URL: nexusrepo-0.2.0-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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b091416fd083e3897a06fa6dcc70067fad46edb3ab236ed99b1b4525c9cf4d41
MD5 977260d21f8d6a6a3703a10064b6f9db
BLAKE2b-256 1c4623f9dfb5c318c82b4c865a5fc22af1cf05020e16e9e68774d6c2e23a0b5d

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