Skip to content

Commit

Permalink
📰 Page title (#311)
Browse files Browse the repository at this point in the history
* Adds title customization

* Fixes lint errors

* Uses app_title for app title, title for page title

* Consistent config naming

* Cleaner syntax with or

* Removes title from error page to avoid erroring during error
  • Loading branch information
mrharpo authored Oct 12, 2023
1 parent 9a5a604 commit 855a71c
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 27 deletions.
49 changes: 25 additions & 24 deletions starlette_admin/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ def _setup_templates(self) -> None:
)
# globals
templates.env.globals["views"] = self._views
templates.env.globals["title"] = self.title
templates.env.globals["app_title"] = self.title
templates.env.globals["is_auth_enabled"] = self.auth_provider is not None
templates.env.globals["__name__"] = self.route_name
templates.env.globals["logo_url"] = self.logo_url
Expand Down Expand Up @@ -333,6 +333,7 @@ async def _render_list(self, request: Request) -> Response:
{
"request": request,
"model": model,
"title": model.title(request),
"_actions": await model.get_all_actions(request, RequestAction.LIST),
"__js_model__": await model._configs(request),
},
Expand All @@ -352,6 +353,7 @@ async def _render_detail(self, request: Request) -> Response:
model.detail_template,
{
"request": request,
"title": model.title(request),
"model": model,
"raw_obj": obj,
"obj": await model.serialize(obj, request, RequestAction.DETAIL),
Expand All @@ -364,26 +366,25 @@ async def _render_create(self, request: Request) -> Response:
request.state.action = RequestAction.CREATE
identity = request.path_params.get("identity")
model = self._find_model_from_identity(identity)
config = {"request": request, "title": model.title(request), "model": model}
if not model.is_accessible(request) or not model.can_create(request):
raise HTTPException(HTTP_403_FORBIDDEN)
if request.method == "GET":
return self.templates.TemplateResponse(
model.create_template,
{"request": request, "model": model},
)
return self.templates.TemplateResponse(model.create_template, config)
form = await request.form()
dict_obj = await self.form_to_dict(request, form, model, RequestAction.CREATE)
try:
obj = await model.create(request, dict_obj)
except FormValidationError as exc:
return self.templates.TemplateResponse(
model.create_template,
config.update(
{
"request": request,
"model": model,
"errors": exc.errors,
"obj": dict_obj,
},
}
)
return self.templates.TemplateResponse(
model.create_template,
config,
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
)
pk = getattr(obj, model.pk_attr) # type: ignore
Expand All @@ -406,29 +407,29 @@ async def _render_edit(self, request: Request) -> Response:
obj = await model.find_by_pk(request, pk)
if obj is None:
raise HTTPException(HTTP_404_NOT_FOUND)
config = {
"request": request,
"title": model.title(request),
"model": model,
"raw_obj": obj,
"obj": await model.serialize(obj, request, RequestAction.EDIT),
}
if request.method == "GET":
return self.templates.TemplateResponse(
model.edit_template,
{
"request": request,
"model": model,
"raw_obj": obj,
"obj": await model.serialize(obj, request, RequestAction.EDIT),
},
)
return self.templates.TemplateResponse(model.edit_template, config)
form = await request.form()
dict_obj = await self.form_to_dict(request, form, model, RequestAction.EDIT)
try:
obj = await model.edit(request, pk, dict_obj)
except FormValidationError as exc:
return self.templates.TemplateResponse(
model.edit_template,
config.update(
{
"request": request,
"model": model,
"errors": exc.errors,
"obj": dict_obj,
},
}
)
return self.templates.TemplateResponse(
model.edit_template,
config,
status_code=HTTP_422_UNPROCESSABLE_ENTITY,
)
pk = getattr(obj, model.pk_attr) # type: ignore
Expand Down
2 changes: 1 addition & 1 deletion starlette_admin/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
{% block head_meta %}{% endblock %}
{% block title %}<title>{{ title }}</title>{% endblock %}
{% block title %}<title>{{ title or app_title }}</title>{% endblock %}
<link rel="stylesheet" href="{{ url_for(__name__ ~ ':statics', path='css/tabler.min.css') }}">
<link rel="stylesheet" href="{{ url_for(__name__ ~ ':statics', path='css/fontawesome.min.css') }}">
<style>
Expand Down
2 changes: 1 addition & 1 deletion starlette_admin/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h1 class="navbar-brand navbar-brand-autodark">
height="32"
class="navbar-brand-image"/>
{% else %}
<h3>{{ title }}</h3>
<h3>{{ app_title }}</h3>
{% endif %}
</a>
</h1>
Expand Down
8 changes: 7 additions & 1 deletion starlette_admin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class BaseView:
label: str = ""
icon: Optional[str] = None

def title(self, request: Request) -> str:
"""Return the title of the view to be displayed in the browser tab"""
return self.label

def is_active(self, request: Request) -> bool:
"""Return true if the current view is active"""
return False
Expand Down Expand Up @@ -159,7 +163,9 @@ def __init__(

async def render(self, request: Request, templates: Jinja2Templates) -> Response:
"""Default methods to render view. Override this methods to add your custom logic."""
return templates.TemplateResponse(self.template_path, {"request": request})
return templates.TemplateResponse(
self.template_path, {"request": request, "title": self.title(request)}
)

def is_active(self, request: Request) -> bool:
return request.scope["path"] == self.path
Expand Down

0 comments on commit 855a71c

Please sign in to comment.