Skip to main content

A common crud framework for web.

Project description

pycrud

codecov

An async crud framework for RESTful API.

Features:

  • Do CRUD operations by json.

  • Easy to integrate with web framework.

  • Works with popular orm.

  • Role based permission system

  • Data validate with pydantic.

  • Tested coveraged

Install:

pip install pycrud==1.0.0a1

Examples:

CRUD service by fastapi and SQLAlchemy

import uvicorn
from typing import Optional
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware

from model_sqlalchemy import engine, UserModel, TopicModel
from pycrud import Entity, ValuesToUpdate, ValuesToCreate, UserObject
from pycrud.crud.ext.sqlalchemy_crud import SQLAlchemyCrud
from pycrud.helpers.fastapi_ext import PermissionDependsBuilder

# Crud Initialize

class User(Entity):
    id: Optional[int]
    nickname: str
    username: str
    password: str = 'password'


c = SQLAlchemyCrud(None, {
    User: 'users'
}, engine)


class PDB(PermissionDependsBuilder):
    @classmethod
    async def validate_role(cls, user: UserObject, current_request_role: str) -> RoleDefine:
        return c.default_role

    @classmethod
    async def get_user(cls, request: Request) -> UserObject:
        pass

# Web Service

app = FastAPI()
app.add_middleware(CORSMiddleware, allow_origins=['*'], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])


@app.post("/user/create", response_model=User.dto.resp_create())
async def user_create(item: User.dto.get_create()):
    return await c.insert_many(User, [ValuesToCreate(item)])  # response id list: [1]


@app.get("/user/list", response_model=User.dto.resp_list())
async def user_list(query=PDB.query_info_depends(User)):
    return [x.to_dict() for x in await c.get_list(query)]


@app.post("/user/update", response_model=User.dto.resp_update())
async def user_list(item: User.dto.get_update(), query=PDB.query_info_depends(User)):
    return await c.update(query, ValuesToUpdate(item))


@app.post("/user/delete", response_model=User.dto.resp_delete())
async def user_delete(query=PDB.query_info_depends(User)):
    return await c.delete(query)


print('Service Running ...')
uvicorn.run(app, host='0.0.0.0', port=3000)

See docs at http://localhost:3000/redoc

You can make requests like:

http://localhost:3000/topic/list?id.eq=1 http://localhost:3000/topic/list?id.gt=1 http://localhost:3000/topic/list?id.in=[2,3] http://localhost:3000/topic/list?user_id.eq=1

CRUD service with permission

See Examples

Query filter

from pycrud.values import ValuesToUpdate
from pycrud.query import QueryInfo


async def fetch_list():
    # dsl version
    q1 = QueryInfo.from_table(User, where=[
        User.id == 1
    ])

    # json verison
    q2 = QueryInfo.from_json(User, {
        'id.eq': 1
    })

    lst = await c.get_list(q1)
    print([x.to_dict() for x in lst])


async def update_by_ids():
    v = ValuesToUpdate({'nickname': 'bbb', 'username': 'u2'})

    # from dsl
    q1 = QueryInfo.from_table(User, where=[
        User.id.in_([1, 2, 3])
    ])

    q2 = QueryInfo.from_json(User, {
        'id.in': [1,2,3]
    })

    lst = await c.update(q1, v)
    print(lst)


async def complex_filter_dsl():
    # $or: (id < 3) or (id > 5)
    (User.id < 3) | (User.id > 5)

    # $and: 3 < id < 5
    (User.id > 3) & (User.id < 5)

    # $not: not (3 < id < 5)
    ~((User.id > 3) & (User.id < 5))
    
    # logical condition: (id == 3) or (id == 4) or (id == 5)
    (User.id != 3) | (User.id != 4) | (User.id != 5)

    # logical condition: (3 < id < 5) or (10 < id < 15)
    ((User.id > 3) & (User.id < 5)) | ((User.id > 10) & (User.id < 15))


async def complex_filter_json():
    # $or: (id < 3) or (id > 5)
    QueryInfo.from_json(User, {
        '$or': {
            'id.lt': 3,  
            'id.gt': 5 
        }
    })
    
    # $and: 3 < id < 5
    QueryInfo.from_json(User, {
        '$and': {
            'id.gt': 3,  
            'id.lt': 5 
        }
    })
    
    # $not: not (3 < id < 5)
    QueryInfo.from_json(User, {
        '$not': {
            'id.gt': 3,  
            'id.lt': 5 
        }
    })

    # logical condition: (id == 3) or (id == 4) or (id == 5)
    QueryInfo.from_json(User, {
        '$or': {
            'id.eq': 3,  
            'id.eq.2': 4,
            'id.eq.3': 5, 
        }
    })

    # logical condition: (3 < id < 5) or (10 < id < 15)
    QueryInfo.from_json(User, {
        '$or': {
            '$and': {
                'id.gt': 3,
                'id.lt': 5
            },
            '$and.2': {
                'id.gt': 10,
                'id.lt': 15
            }
        }
    })

Operators

type operator text
compare EQ ('eq', '==')
compare NE ('ne', '!=')
compare LT ('lt', '<')
compare LE ('le', '<=')
compare GE ('ge', '>=')
compare GT ('gt', '>')
relation IN ('in',)
relation NOT_IN ('notin', 'not in')
relation IS ('is',)
relation IS_NOT ('isnot', 'is not')
relation PREFIX ('prefix',)
relation CONTAINS_ALL ('contains_all',)
relation CONTAINS_ANY ('contains_any',)
logic AND ('and',)
logic OR ('or',)

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

pycrud-1.0.0a1.tar.gz (27.2 kB view hashes)

Uploaded Source

Built Distribution

pycrud-1.0.0a1-py3-none-any.whl (34.8 kB view hashes)

Uploaded Python 3

Supported by

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