Piccolo Admin provides a simple yet powerful admin interface on top of Piccolo tables

Overview

Logo

Piccolo Admin

Documentation Status

Piccolo Admin provides a simple yet powerful admin interface on top of Piccolo tables - allowing you to easily add / edit / filter your data.

Screenshot

It was created at a design agency to serve the needs of customers who demand a high quality, beautiful admin interface for their websites. Our goal is to create a world class admin interface, akin to Wordpress or Django.

It's built using the latest technologies, with Vue JS on the front end, and a modern REST backend.

Try it

Try it online (username: piccolo, password: piccolo123).

Local Demo

To run a demo locally, using Python 3.7 or above:

pip install piccolo_admin
admin_demo

And then just launch localhost:8000 in your browser.

To see what happens behind the scenes, see piccolo_admin/example.py.

In a few lines of code we are able to:

  • Define our models
  • Setup a database
  • Create a REST API
  • Setup a web server and admin interface

ASGI

Since the admin is an ASGI app, you can either run it standalone like in the demo, or integrate it with a larger ASGI app.

For example, using Starlette routes:

from piccolo_admin.endpoints import create_admin
from starlette.routing import Router, Route
import uvicorn

from my_project.tables import Director, Movie


# The `allowed_hosts` argument is required when running under HTTPS. It's used
# for additional CSRF defence.
admin = create_admin([Director, Movie], allowed_hosts=['my_site.com'])


router = Router([
    Route(path="/", endpoint=Hello),
    Mount(path="/admin/", app=admin),
])


if __name__ == '__main__':
    uvicorn.run(router)

Full docs

Full documentation is available on Read the docs.

Comments
  • Try `piccolo_admin` with Starlite

    Try `piccolo_admin` with Starlite

    It was reported that Piccolo Admin doesn't work with the Starlite framework.

    It should be possible to mount Piccolo Admin:

    https://starlite-api.github.io/starlite/usage/2-route-handlers/3-asgi-route-handlers/

    Tasks required:

    • [x] Try getting Piccolo admin working with Starlite
    • [x] If it doesn't work, try and work out why
    good first issue 
    opened by dantownsend 46
  • Implement TableConfig class

    Implement TableConfig class

    Currently, create_admin accepts a list of Table subclasses. This can be modified to accept either Table subclasses, or instances of a new class called TableConfig.

    TableConfig will be a dataclass which accepts a table argument, as well as a bunch of configuration options. For example:

    @dataclasses.dataclass
    class TableConfig:
        """
        :param list_columns:
            Used to specify which columns are shown on the list page. If None,
            all are shown.
        :param list_filters:
            Used to specify which filters are shown on the list page. If None,
            all are shown.
    
        """
        table: Type[Table]
        list_columns: Optional[List[Union[str, Column]] = None
        list_filters: Optional[List[Union[str, Column]] = None
        # Plus some additional options, which haven't been finalised.
        ...
    
    app = create_admin(
        tables=[
            SomeTable,
            TableConfig(
                table=MyTable,
                list_columns=[MyTable.name],
                list_filters=[MyTable.name]
            )
        ]
    )
    

    It will allow more fine grained control of the how the admin looks.

    enhancement medium priority proposal - input needed 
    opened by dantownsend 27
  • Automate running of Cypress tests

    Automate running of Cypress tests

    Now we have some basic Cypress tests, it is worth investigating how we can run these as part of GitHub actions.

    Cypress tests can be notoriously slow, so we might not want to run them on every commit - we will have to see what the performance is like.

    good first issue testing 
    opened by dantownsend 25
  • initial commit for migrate from Vue2 to Vue3

    initial commit for migrate from Vue2 to Vue3

    Based on #87. Work in progress

    • [x] fixing login process
    • [x] replacing deprecated features form Vue2 (Vue.set(), Vue.delete(), filters in template) with Vue3 features
    • [x] upgraded major library dependencies for working with Vue 3
    • [x] removing vue-json-excel and making our own implementation of CSV export
    • [x] fixing RowListing and CRUD
    • [x] fixing sorting and filtering
    • [x] fixing reference table search results
    • [x] added basic types
    • [x] custom forms
    • [x] fixing nullable fields
    • [x] TableConfig
    opened by sinisaos 24
  • add translations

    add translations

    Related to #173.

    Result is:

    https://user-images.githubusercontent.com/30960668/177712285-56767f52-468d-434e-a6b4-39e95edf6329.mp4

    To add a new translation, we just need to add a new json (eg. german.json) to assets/locales and update main.ts to register the new translation.

    opened by sinisaos 15
  • Make sure Piccolo admin works with custom primary key columns

    Make sure Piccolo admin works with custom primary key columns

    When using custom primary key columns, for example:

    class MyTable(Table):
        pk = UUID(primary_key=True)
    

    There are likely to be some edge cases not currently supported by Piccolo admin.

    enhancement high priority 
    opened by dantownsend 15
  • adding export to csv

    adding export to csv

    @dantownsend this is my try on exporting to csv. Probably it be slow for large and complex tables due to passing total number of rows to PiccoloCRUD __page_size param , but it's just idea.

    opened by sinisaos 14
  • File upload support

    File upload support

    Based on https://github.com/piccolo-orm/piccolo_admin/pull/182

    @sinisaos I've done a bunch of work on this.

    The main changes are:

    • Added extra security based on this OWASP doc
    • It now supports all kinds of files - e.g. video as well
    • Added a media preview window, so the user can see the full sized image or video within Piccolo Admin
    • Array, Varchar, and Text columns can all be used as media columns

    You can see the changes here:

    https://user-images.githubusercontent.com/350976/181996743-17dae1d0-8b13-42de-89c0-b16c5643997b.mp4

    The biggest change from the original PR is it saves a unique identifier for the file in the database, rather than the URL. There are two reasons for this:

    • If the user decides to host their media files somewhere else, they don't have to update anything in the database.
    • It's the only way to get it working with S3. Each time someone accesses a file in S3 we need to generate a signed URL, which is only valid for a short period of time, so we can't store the URL in the database.

    I think it's about 80% done. It's a massive feature, but a really cool one.

    Things that need doing still:

    • [x] Update the docs
    • [ ] I need to add your file upload button back - it looks nicer than what's there now
    • [x] Add links on the row detail page for viewing images
    • [x] Maybe add S3 support, so we know the API works properly with it before releasing it
    • [x] The media is always served from /api/media-files/ at the moment. It's ignoring the media_url setting in LocalStorage. That needs some thinking about.
    • [x] We used to have media_columns and media_storage arguments in TableConfig. I changed it slightly (now there's just media_columns, which maps a column to a MediaStorage) because I can imagine use cases where you want some columns to store files in one place, and other columns to store files in another place. Also, you might only allow images in some columns, and videos in other columns. It still needs a bit of thinking about.
    • [x] I might move a bunch of the logic to Piccolo API, so it can also be used with PiccoloCRUD standalone.

    I removed your image previews from RowListing.vue for now. I liked the way they looked, but because we're not creating thumbnails for the images, if the page is showing 100 rows, it will pull down 100 full sizes images, which would slow things down too much. Once we work out thumbnails I would like to add it back.

    enhancement 
    opened by dantownsend 11
  • Wysiwyg editor

    Wysiwyg editor

    @dantownsend are you perhaps interested in adding wysiwyg editor to textarea fields?

    https://user-images.githubusercontent.com/30960668/158114813-3fa9b405-e87e-438e-84a1-5a2395cc145e.mov

    enhancement 
    opened by sinisaos 10
  • `TableConfig` media handlers

    `TableConfig` media handlers

    This is a big task, but unlocks a lot of great functionality in the admin.

    Piccolo doesn't have a particular column type for storing media (images, video etc). It's possible to store them in binary columns, but this is generally frowned upon as it quickly leads to database bloat (and database storage is typically much more expensive than object storage).

    The usual approach for storing media is to put the file in object storage (like S3), or in a local directory, and store a reference to it in the database (for example a URL or path).

    Initially we can just store the media files in a local directory, but supporting the S3 protocol would be great in the future.

    The steps required to implement this:

    MediaHandler class

    # This is just an abstract base class for all other media handlers:
    class MediaHandler:
        pass
    
    @dataclass
    class LocalMediaHandler(MediaHandler):
        root_path: str
    
        def store_file(self, file):
            ...
    
        def retrieve_file(self, path: str):
            ...
    

    TableConfig changes

    media_handler = LocalMediaHandler(root_path='/var/www/files/')
    
    app = create_admin(
        TableConfig(
            Movie,
            media_handler=media_handler,
            media_columns=[Movie.poster]
        )
    )
    

    PiccoloCRUD changes

    There will be a new endpoint, something like:

    /tables/director/1/media?column=poster
    

    Which can be used to retrieve the actual media file.

    UI improvements

    The UI will know if a column is used for media storage by inspecting the JSON schema:

    /api/tables/director/schema
    

    PiccoloCRUD would've added an extra field to it called 'media_columns', using create_pydantic_model's schema_extra_kwargs feature.

    The UI would then render a file upload box for that field. In the future we could support simple editing functionality like cropping images (there are several JS libraries for this), but that's down the road.

    enhancement proposal - input needed 
    opened by dantownsend 10
  • Add custom widget for Interval fields

    Add custom widget for Interval fields

    Any Interval fields are shown as text boxes, where you input a number of seconds. It works fine, but could be more user friendly.

    The schema for a table with an Interval column looks like this (accessible via /api/tables/my_table/schema).

    {
        "title": "MyTableIn",
        "type": "object",
        "properties": {
            "interval": {
                "title": "Interval",
                "extra": {},
                "nullable": false,
                "type": "number",
                "format": "time-delta"
            }
        }
    }
    

    We can tell if it's an Interval from the format field in the schema, which is "time-delta".

    enhancement 
    opened by dantownsend 10
  • Cannot edit non-default primary key in admin

    Cannot edit non-default primary key in admin

    Hi,

    I have a model where a PK is defined on an explicit Varchar field, like this

    class MyModel(Table):
        identifier = columns.Varchar(length=64, primary_key=True)
       .....  other fields .....
    

    It's entirely on purpose. I don't want the PK to be an auto-incremented integer. I want a random string as PK. ORM allows for that, which is good.

    The problem is trying to add those objects via admin. Admin UI does not show any textbox to enter the PK value and it is not possible to add those objects.

    Apparently admin assumes that primary key column is always an auto-incremented integer. But ORM allows to have PK on non-int non-incrementable column.

    Any advice how to work around this problem?

    opened by PawelRoman 5
  • datetime picker doesn't support minute granularity

    datetime picker doesn't support minute granularity

    I've created a table entry like this: expiry = Timestamptz(null=True)

    A few things I'm noticing in piccolo-admin

    • it's not possible for the datetime to be None, piccolo-admin always suggests the current time/date
    • the datetime picker uses a 12-hour (pm/am) type clock. It would be nice if that was configurable for "non-US" users

    I'd really like it to be possible to disable the datetime picker altogether and have users type in a datetime string instead, with the option of having the field empty (indicating None) too.

    opened by trondhindenes 3
  • allow BYO auth backend

    allow BYO auth backend

    Allows replacing the built-in auth backend with a custom one.

    This allowed me to do:

    class HackyAuthUser(BaseUser):
        def __init__(self, user_id: str = 'unknown', display_name: str = 'unknown'):
            self._user_id = user_id
            self._display_name = display_name
    
        @property
        def is_authenticated(self) -> bool:
            return True
    
        @property
        def display_name(self) -> str:
            return self._display_name
    
        @property
        def user_id(self) -> str:
            return self._user_id
    
    
    class HackyAuthBackend(AuthenticationBackend):
        def __init__(self, header_name):
            self.header_name = header_name
    
        async def authenticate(self, conn):
            if self.header_name not in conn.headers:
                raise AuthenticationError('Invalid credentials')
            user_name = conn.headers[self.header_name]
            return AuthCredentials(scopes=[]), HackyAuthUser(user_name, user_name)
    
    
    app = FastAPI(
        routes=[
            Mount('/admin/', create_admin(
                tables=APP_CONFIG.table_classes,
                auth_backend=HackyAuthBackend(header_name='Authorization'))
                  ),
        ],
    )
    

    It would be cool if it was somehow possible to override the default "non-authenticated" behavior, and for example have admin-api redirect the user to another login url instead of the built-in one, but I didn't find a clean way to do that.

    opened by trondhindenes 0
  • allow completely disabling built-in auth

    allow completely disabling built-in auth

    Hi, We're looking to use piccolo-admin in a project, but we want to plug in our internal auth mechanisms, which we typically use together with oauth-proxy to wrap 3rd party apps in our auth layer.

    Because of this, I'd like to use piccolo-admin but without any of the built-in authz/authn functionality. I'd like piccolo-admin to simply assume that every request comes from an admin users (we'll ofc handle authz/authn outside piccolo-admin).

    I haven't yet looked at the code, but it would be interesting to hear of something like this is already supported or planned. From what I can see from the create_admin 's parameters there doesn't seem to be any obvious way of achieving what I want today.

    opened by trondhindenes 7
  • When the id field is hidden in TableConfig, there is no way to edit a record

    When the id field is hidden in TableConfig, there is no way to edit a record

    So we have an UUID primary keys and want to hide them in admin, but that's happens:

    image

    It would be cool if the record link field was parameterized in TableConfig

    opened by metakot 11
Releases(0.39.0)
  • 0.39.0(Dec 7, 2022)

    If an Array column has choices specified, then Piccolo Admin will show dropdowns, so the user can pick one of the choices.

    206292810-23b47d29-ff7f-4d04-8c70-fd5c8d790629

    Thanks to @sinisaos for help testing it.

    Source code(tar.gz)
    Source code(zip)
  • 0.38.0(Nov 18, 2022)

  • 0.37.0(Nov 16, 2022)

    • Python 3.11 is now officially supported.
    • Added debug mode: create_admin(tables=[MyTable], debug=True).
    • Logging exceptions for 500 errors.
    • Fixed a typo in the docs about how to use validators (thanks to @sinisaos for reporting this).
    • Updated the tests for Starlette / FastAPI's new test client. This means that fastapi==0.87.0 / starlette==0.21.0 are now the minimum versions supported. Thanks to @sinisaos for this.
    Source code(tar.gz)
    Source code(zip)
  • 0.36.0(Nov 11, 2022)

    Lots of small enhancements.

    • Fixed bugs with the foreign key selector. Sometimes the edit button didn't work. Also, sometimes the value shown in the input box wasn't refreshing when navigating to a new page.
    • The HTML title now matches the site_name parameter in create_admin (thanks to @sinisaos for this).
    • Updated Vue to the latest version.
    • Internal code refactoring.
    Source code(tar.gz)
    Source code(zip)
  • 0.35.0(Oct 14, 2022)

    Validators can now be specified in TableConfig.

    This allows fine grained access control - for example, only allowing some users to send POST requests to certain API endpoints:

    from piccolo_api.crud.endpoints import PiccoloCRUD
    from starlette.exceptions import HTTPException
    from starlette.requests import Request
    
    
    async def manager_only(
        piccolo_crud: PiccoloCRUD,
        request: Request
    ):
        # The Piccolo `BaseUser` can be accessed from the request.
        user = request.user.user
    
        # Assuming we have another database table where we record
        # users with certain permissions.
        manager = await Manager.exists().where(manager.user == user)
    
        if not manager:
            # Raise a Starlette exception if we want to reject the
            # request.
            raise HTTPException(
                status_code=403,
                detail="Only managers are allowed to do this"
            )
    
    
    admin = create_admin(
        tables=TableConfig(
            Movie,
            validators=Validators(post_single=manager_only)
        )
    )
    
    Source code(tar.gz)
    Source code(zip)
  • 0.34.0(Oct 11, 2022)

  • 0.33.1(Sep 14, 2022)

  • 0.33.0(Sep 8, 2022)

  • 0.32.0(Sep 8, 2022)

    Camelcase column names could break parts of Piccolo Admin. It now works as expected:

    class Person(Table):
        # This now works:
        firstName = Varchar()
    

    Even though camelcase is unusual in Python, a user may be using an existing database, so it makes sense to support it. Thanks to @sumitsharansatsangi for reporting this issue.

    Source code(tar.gz)
    Source code(zip)
  • 0.31.2(Sep 5, 2022)

    When piccolo_admin is installed, an admin_demo script is made available on the command line, which launches a Piccolo Admin demo.

    It wasn't working due to a missing folder, which has now been fixed.

    Source code(tar.gz)
    Source code(zip)
  • 0.31.1(Aug 29, 2022)

  • 0.31.0(Aug 29, 2022)

  • 0.30.0(Aug 28, 2022)

  • 0.29.1(Aug 11, 2022)

    The media endpoints now obey the read_only option of create_admin. Read only mode is used for online demos.

    Thanks to @sinisaos for adding this.

    Source code(tar.gz)
    Source code(zip)
  • 0.29.0(Aug 6, 2022)

    Added media upload support - to both a local folder, and S3.

    Images, videos, PDFs, and audio files can be viewed within the UI.

    This is the one of the biggest updates we've ever made, and are excited to share!

    media_viewer_image

    Thanks to @sinisaos for all of the help.

    Source code(tar.gz)
    Source code(zip)
  • 0.28.0(Jul 29, 2022)

  • 0.27.0(Jul 27, 2022)

  • 0.26.1(Jul 25, 2022)

signal-cli-rest-api is a wrapper around signal-cli and allows you to interact with it through http requests

signal-cli-rest-api signal-cli-rest-api is a wrapper around signal-cli and allows you to interact with it through http requests. Features register/ver

Sebastian Noel Lübke 31 Dec 09, 2022
I'm curious if pydantic + fast api can be sensibly used with DDD + hex arch methodology

pydantic-ddd-exploration I'm curious if pydantic + fast api can be sensibly used with DDD + hex arch methodology Prerequisites nix direnv (nix-env -i

Olgierd Kasprowicz 2 Nov 17, 2021
python template private service

Template for private python service This is a cookiecutter template for an internal REST API service, written in Python, inspired by layout-golang. Th

UrvanovCompany 15 Oct 02, 2022
API & Webapp to answer questions about COVID-19. Using NLP (Question Answering) and trusted data sources.

This open source project serves two purposes. Collection and evaluation of a Question Answering dataset to improve existing QA/search methods - COVID-

deepset 329 Nov 10, 2022
Mnist API server w/ FastAPI

Mnist API server w/ FastAPI

Jinwoo Park (Curt) 8 Feb 08, 2022
api versioning for fastapi web applications

fastapi-versioning api versioning for fastapi web applications Installation pip install fastapi-versioning Examples from fastapi import FastAPI from f

Dean Way 472 Jan 02, 2023
Basic FastAPI starter with GraphQL, Docker, and MongoDB configurations.

FastAPI + GraphQL Starter A python starter project using FastAPI and GraphQL. This project leverages docker for containerization and provides the scri

Cloud Bytes Collection 1 Nov 24, 2022
Example app using FastAPI and JWT

FastAPI-Auth Example app using FastAPI and JWT virtualenv -p python3 venv source venv/bin/activate pip3 install -r requirements.txt mv config.yaml.exa

Sander 28 Oct 25, 2022
python fastapi example connection to mysql

Quickstart Then run the following commands to bootstrap your environment with poetry: git clone https://github.com/xiaozl/fastapi-realworld-example-ap

55 Dec 15, 2022
Install multiple versions of r2 and its plugins via Pip on any system!

r2env This repository contains the tool available via pip to install and manage multiple versions of radare2 and its plugins. r2-tools doesn't conflic

radare org 18 Oct 11, 2022
A simple api written in python/fastapi that serves movies from a cassandra table.

A simple api written in python/fastapi that serves movies from a cassandra table. 1)clone the repo 2)rename sample_global_config_.py to global_config.

Sreeraj 1 Aug 26, 2021
FastAPI framework plugins

Plugins for FastAPI framework, high performance, easy to learn, fast to code, ready for production fastapi-plugins FastAPI framework plugins Cache Mem

RES 239 Dec 28, 2022
A Nepali Dictionary API made using FastAPI.

Nepali Dictionary API A Nepali dictionary api created using Fast API and inspired from https://github.com/nirooj56/Nepdict. You can say this is just t

Nishant Sapkota 4 Mar 18, 2022
Fastapi practice project

todo-list-fastapi practice project How to run Install dependencies npm, yarn: standard-version, husky make: script for lint, test pipenv: virtualenv +

Deo Kim 10 Nov 30, 2022
Htmdf - html to pdf with support for variables using fastApi.

htmdf Converts html to pdf with support for variables using fastApi. Installation Clone this repository. git clone https://github.com/ShreehariVaasish

Shreehari 1 Jan 30, 2022
fastapi-crud-sync

Developing and Testing an API with FastAPI and Pytest Syncronous Example Want to use this project? Build the images and run the containers: $ docker-c

59 Dec 11, 2022
Backend, modern REST API for obtaining match and odds data crawled from multiple sites. Using FastAPI, MongoDB as database, Motor as async MongoDB client, Scrapy as crawler and Docker.

Introduction Apiestas is a project composed of a backend powered by the awesome framework FastAPI and a crawler powered by Scrapy. This project has fo

Fran Lozano 54 Dec 13, 2022
🤪 FastAPI + Vue构建的Mall项目后台管理

Mall项目后台管理 前段时间学习Vue写了一个移动端项目 https://www.charmcode.cn/app/mall/home 然后教程到此就结束了, 我就总感觉少点什么,计划自己着手写一套后台管理。 相关项目 移动端Mall项目源码(Vue构建): https://github.com/

王小右 131 Jan 01, 2023
Twitter API with fastAPI

Twitter API with fastAPI Content Forms Cookies and headers management Files edition Status codes HTTPExceptions Docstrings or documentation Deprecate

Juan Agustin Di Pasquo 1 Dec 21, 2021
A Python pickling decompiler and static analyzer

Fickling Fickling is a decompiler, static analyzer, and bytecode rewriter for Python pickle object serializations. Pickled Python objects are in fact

Trail of Bits 162 Dec 13, 2022