starlette-admin

repository·main·Indexed 21 days ago

https://github.com/jowilf/starlette-admin

A fast, beautiful, and extensible administrative interface framework for Starlette and FastAPI applications. It provides a complete CRUD solution compatible with multiple ORMs and ODMs, including SQLAlchemy, SQLModel, MongoEngine, and ODMantic.

Tokens
35.8K
Snippets
109
Records
146
Agent score
77%

What's inside starlette-admin

  1. Supported ORMs and Data Layers

    main

    Unlike many admin solutions that are tied to a specific ORM, starlette-admin is designed to work with various data layers. Supported out-of-the-box integrations include:

    • SQLAlchemy
    • SQLModel
    • MongoEngine
    • ODMantic
    • Custom backends (via implementing a custom data layer)
  2. Use starlette-admin views to customize the admin interface

    main

    The starlette_admin.views module provides the building blocks for defining how data and navigation are presented in the admin interface. You can use these components to create standard views for your models or implement entirely custom logic.

    Key components include:

    • BaseView: The foundation for all view types.
    • BaseModelView: A specialized view designed to work with database models (CRUD operations).
    • CustomView: Used when you need to implement logic that doesn't map directly to a standard model CRUD lifecycle.
    • DropDown and Link: UI components used within views to manage navigation and interactive elements.
    from starlette_admin.views import BaseModelView, CustomView
    
    # Example: Using a BaseModelView for a specific model
    class UserView(BaseModelView):
        model = User
    
    # Example: Using a CustomView for non-model logic
    class DashboardView(CustomView):
        def render(self):
            # Custom rendering logic here
            pass
  3. Customize object representation in the admin interface

    main

    You can control how objects are represented in the admin interface (e.g., in Select2 dropdowns or list views) by implementing special methods on your models:

    • __admin_repr__: Defines the general representation of the object.
    • __admin_select2_repr__: Defines the representation specifically for Select2 components.
  4. Quickstart: Create an admin interface with SQLAlchemy

    main

    To set up a basic admin interface, follow these steps:

    1. Define your model: Create your SQLAlchemy models as usual.
    2. Create the Admin instance: Initialize the Admin class from starlette_admin.contrib.sqla, passing your database engine and an optional title.
    3. Add views: Use admin.add_view() with a ModelView instance of your model to enable CRUD operations.
    4. Mount to your app: Call admin.mount_to(app) on your Starlette or FastAPI application instance.

    The admin interface will be accessible at /admin by default.

    from sqlalchemy import create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import Mapped, mapped_column
    from starlette.applications import Starlette
    
    from starlette_admin.contrib.sqla import Admin, ModelView
    
    Base = declarative_base()
    engine = create_engine("sqlite:///test.db", connect_args={"check_same_thread": False})
    
    # Define your model
    class Post(Base):
        __tablename__ = "posts"
    
        id: Mapped[int] = mapped_column(primary_key=True)
        title: Mapped[str]
    
    Base.metadata.create_all(engine)
    
    app = Starlette()  # FastAPI() also works
    
    # Create admin
    admin = Admin(engine, title="Example: SQLAlchemy")
    
    # Add view
    admin.add_view(ModelView(Post))
    
    # Mount admin to your app
    admin.mount_to(app)
  5. Initialize the Admin interface

    main

    To start using starlette-admin, initialize the Admin class. The initialization parameters depend on the database engine you are using. You must import Admin from the specific contribution module corresponding to your ORM/ODM.

    • SQLAlchemy: Import from starlette_admin.contrib.sqla and pass the engine.
    • SQLModel: Import from starlette_admin.contrib.sqlmodel and pass the engine.
    • MongoEngine: Import from starlette_admin.contrib.mongoengine. No engine is passed to the constructor.
    • ODMantic: Import from starlette_admin.contrib.odmantic and pass the engine (e.g., AIOEngine()).

    Always provide a title string to identify your admin panel.

    from starlette_admin.contrib.sqla import Admin
    engine = create_engine("sqlite:///basic.db")
    admin = Admin(engine, title="My Admin")
  6. Customize form rendering for custom fields

    main

    To change how a field appears in forms (Create/Edit), create a Jinja2 template file in your forms directory and assign it to the form_template attribute of your field class.

    Available Jinja2 variables in the template:

    • field: The field instance.
    • error: The error message (if any) from FormValidationError.
    • data: The current value (available during Edit or when validation fails).
    • action: The current action (EDIT or CREATE).
    @dataclass
    class CustomField(BaseField):
        form_template: str = "forms/custom.html"
    <div class="{%if error%}is-invalid{%endif%}">
        <input id="{{field.id}}" name="{{field.id}}" ... />
        {% if field.help_text %}
        <small class="form-hint">{{field.help_text}}</small>
        {% endif %}
    </div>
    {% if error %}
    <div class="invalid-feedback">{{error}}</div>
    {% endif %}
  7. Run the Authlib OAuth2 example

    main

    To run the provided OAuth2/OIDC example, follow these steps:

    1. Clone the repository and navigate to the directory.
    2. Configure credentials: Update examples/authlib/config.py with your Auth0 credentials or set them as environment variables (AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET, AUTH0_DOMAIN).
    3. Setup environment: Create and activate a Python virtual environment.
    4. Install dependencies: Use the requirements file located at examples/authlib/requirements.txt.
    5. Start the server: Run the application using uvicorn.
    # Clone and enter repo
    git clone https://github.com/jowilf/starlette-admin.git
    cd starlette-admin
    
    # Setup virtual environment
    python3 -m venv env
    source env/bin/activate
    
    # Install requirements
    pip install -r 'examples/authlib/requirements.txt'
    
    # Run the application
    uvicorn examples.authlib.app:app
  8. Customize list rendering with Datatables

    main

    By default, all fields are rendered as text in the list view. To customize this, you must use a JavaScript function to render the column within the Datatables instance.

    1. Provide a JS file: Override the custom_render_js method in your Admin class to return the URL of your custom JavaScript file.
    2. Implement the render function: In your JS file, add your rendering logic to the render object. The fieldOptions argument contains your field's attributes (serialized via asdict).
    3. Set the key: In your BaseField subclass, set the render_function_key to match the key used in your JavaScript object.
    from starlette_admin.contrib.sqla import Admin as BaseAdmin
    from starlette_admin import BaseField
    from dataclasses import dataclass
    from typing import Optional
    from starlette.requests import Request
    
    # 1. Override Admin to provide the JS file
    class Admin(BaseAdmin):
        def custom_render_js(self, request: Request) -> Optional[str]:
            return request.url_for("statics", path="js/custom_render.js")
    
    # 2. Define the field with the matching key
    @dataclass
    class CustomField(BaseField):
        render_function_key: str = "mycustomkey"
    
    admin = Admin(engine)
    admin.add_view(...)
    Object.assign(render, {
      mycustomkey: function render(data, type, full, meta, fieldOptions) {
        // Your custom rendering logic here
      },
    });
  9. Manage files with MongoEngine

    main

    For MongoDB users, starlette-admin provides out-of-the-box support for file and image management via MongoEngine's FileField and ImageField (including GridFS support).

    To implement this:

    1. Define your document using mongoengine.Document.
    2. Use ImageField or FileField for the desired attributes.
    3. Create a ModelView using starlette_admin.contrib.mongoengine.ModelView.
    4. Register the view with your admin instance using admin.add_view().
    from mongoengine import Document, FileField, ImageField, StringField
    from starlette_admin.contrib.mongoengine import ModelView
    
    
    class Book(Document):
        title = StringField(max_length=50)
        cover = ImageField(thumbnail_size=(128, 128))
        content = FileField()
    
    
    class BookView(ModelView):
        pass
    
    admin.add_view(BookView(Book))
  10. Migrate CustomView definition (v0.3.0 breaking change)

    main

    In version 0.3.0, CustomView definitions were simplified. Instead of creating a new class that inherits from CustomView, you now instantiate CustomView directly with the desired configuration parameters.

    # Now (v0.3.0+)
    admin.add_view(CustomView(label="Home", icon="fa fa-home", path="/home", template_path="home.html"))
    
    # Before (v0.3.0-)
    class HomeView(CustomView):
        label = "Home"
        icon = "fa fa-home"
        path = "/home"
        template_path = "home.html"
    
    admin.add_view(HomeView)
  11. Migrate ModelView definition (v0.3.0 breaking change)

    main

    In version 0.3.0, the way ModelView is defined changed to reduce code size and complexity. Instead of subclassing ModelView to define attributes like icon and label, you now pass these as arguments directly to the ModelView constructor when calling admin.add_view().

    # Now (v0.3.0+)
    class Post:
        id: int
        title: str
    
    admin.add_view(ModelView(Post, icon="fa fa-blog", label="Blog Posts"))
    
    # Before (v0.3.0-)
    class PostView(ModelView, model=Post):
        icon = "fa fa-blog"
        label = "Blog Posts"
    
    admin.add_view(PostView)