At #767, I talked about building a RedisCLI view like in the Flask Admin.
I started building this view, but I realized that routing in the view is a bit different from the Flask Admin.
Flask Admin uses one Blueprint (Router
equivalent in Flask) per view but SQLAdmin registers exposed methods directly to the main Starlette application instance (BaseAdmin.admin
), not a dedicated Router
instance of the view.
So in my case, if I do this:
from sqladmin import BaseView, expose
class RedisCLIView(BaseView):
name = "Redis CLI"
redis_instance = None
identity = "rediscli"
@expose("/rediscli", methods=["GET", "POST"], identity="index")
async def index_page(self, request):
# Do something with redis_instance
return await self.templates.TemplateResponse(request, "sqladmin/redis/index.html")
admin.add_view(RedisCLIView)
The url_for
method won't work as expected.
url_for("admin:rediscli:index")
will raise an error because the view is not registered as a Router
with a name ("rediscli") and the exposed method is not registered as a Route
with a name ("index").
url_for("admin:index")
will work because exposed methods are registered as a Route
to the main Starlette application instance.
In general, every view is expected to have an entry point (like a home page) and other pages. This is generally the index
and other pages.
What happens if we have multiple views with the same entry point name?
from starlette.applications import Starlette
from sqladmin import Admin, BaseView, expose
class RedisCLIView(BaseView):
name = "Redis CLI"
redis_instance = None
identity = "rediscli"
@expose("/rediscli", methods=["GET", "POST"], identity="index")
async def index_page(self, request):
# Do something with redis_instance
return await self.templates.TemplateResponse(request, "sqladmin/redis/index.html")
class RedisCLI1(RedisCLIView):
name = "Redis CLI 1"
redis_instance = None
class RedisCLI2(RedisCLIView):
name = "Redis CLI 2"
redis_instance = None
app = Starlette()
admin = Admin(app)
admin.add_view(RedisCLI1)
admin.add_view(RedisCLI2)
Even though RedisCLI1
and RedisCLI2
are different views, they both have the same entry point (index
) with the same URL (/rediscli
).
Thinking RedisCLIView
comes from SQLAdmin, will cause unexpected behavior because the index
method is already registered.
Every view should have its own Router
and its exposed methods should be registered to that Router
.
I'm actively using Starlette Admin, it doesn't have a built-in expose
method and it has a similar structure to SQLAdmin. The problem that exists here also exists there.
I tried to adopt Flask Admin to work with Starlette but that's not an easy job π.
Since the index
, list
, details
, delete
, create
, edit
, export
, and ajax_lookup
endpoints are registered directly to the main Starlette application instance, we can't override them for each view.
sqladmin/sqladmin/application.py
Lines 387 to 419 in d062cfa
The user might need to override the list
method in the ModelView
but might require different logic per model. So the user must override Admin
directly.
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too