flask-admin 快速打造博客 系列三 (后台模板修改)

  • Post author:
  • Post category:其他


Flask-admin 自定义后台模板


可能有些人不喜欢原始的管理后台,虽然看起来还挺干净简练的,不是我要的样子,可以自定义吗?

答案当然是可以的。

最好是自己通过github下载flask-admin源码,然后自己查看一下后台的源码走向。


clipboard.png

通过这张图,我们也可以了解到模板中,最底层的admin/base.html,其他模板都是通过继承去根据宏去改写具体的显示的。

admin/master.html文件里就是直接引用base.html 没有其他的东西:


{% extends admin_base_template %}

如果我们要改写这个后台的模板,是不是我们只要拿到相应的标签就可以改造了,标签主要就是组件及其数据的html,说白就是wTF在后台生成的代码嵌到模板上,当然,你也可以完全改写了,那也就没有必要用flask-admin的意义了。

我们在base.html 里面看到引入两个其他文件:

{% import 'admin/layout.html' as layout with context -%}
{% import 'admin/static.html' as admin_static with context %}


layout.html

文件是最关键的布局文件


layout.html

主要是定义了菜单的宏:菜单的icon,菜单的遍历显示,菜单的扩展链接,菜单的提示信息(增删改后的提示信息)

还有一个重要的lib.html文件是一个库文件,预定义一些样式和组件,也是可以直接拿来用的。

在base.html 可以看到:

{% block main_menu %}
<ul class="nav navbar-nav">
  {{ layout.menu() }}
</ul>
{% endblock %}

就是菜单直接嵌入layout.html的菜单,所以我们可以直接改base.html 包括layout.html 也给修改成我们的就是实现后台模板的整体修改。

可以直接在

Template目录建立目录admin,创建mybase.html,mylayout.html

然后注册模板到flask-admin:

admin = Admin(app, name='cleanblog', template_mode='bootstrap3', base_template='admin/mybase.html')

只需要两步就能解决问题,其实还有一步就是你要找到一个合适的模板:

我们可以去

https://startbootstrap.com/te…

下载一套自己觉得还可以的bootstrap样式,最好是bootstrap样式的,原因是这样可以减少一些修改设置样式冲突。

我们分几步进行整合

1)寻找模板,并把文件放到static静态目录下:

以startbootstrap-sb-admin-2-gh-pages模板为例:(可以直接百度搜到)

拷贝压缩包的三个目录到static下:dist,js,vendor

2)在template目录建立目录admin并新建文件 mybase.html,和mylayout.html


1.1 mylayout.html


在复制原先的代码进行修改:

{% macro menu(menu_root=None) %}
  {% if menu_root is none %}{% set menu_root = admin_view.admin.menu() %}{% endif %}
  {%- for item in menu_root %}
    {%- if item.is_category() -%}
      {% set children = item.get_children() %}
      {%- if children %}
        {% set class_name = item.get_class_name() %}
        {%- if item.is_active(admin_view) %}
        <li class="active dropdown">
        {% else -%}
        <li class="dropdown">
        {%- endif %}
          <a class="dropdown-toggle" data-toggle="dropdown" href="javascript:void(0)">
            {% if item.class_name %}<span class="{{ item.class_name }}"></span> {% endif %}{{ item.name }}<b class="caret"></b>
          </a>
          <ul class="dropdown-menu">
          {%- for child in children -%}
            {% set class_name = child.get_class_name() %}
            {%- if child.is_active(admin_view) %}
            <li class="active{% if class_name %} {{class_name}}{% endif %}">
            {% else %}
            <li{% if class_name %} class="{{class_name}}"{% endif %}>
            {%- endif %}
              <a href="{{ child.get_url() }}"{% if child.target %} target="{{ child.target }}"{% endif %}>{{ menu_icon(child) }}{{ child.name }}</a>
            </li>
          {%- endfor %}
          </ul>
        </li>
      {% endif %}
    {%- else %}
      {%- if item.is_accessible() and item.is_visible() -%}
        {% set class_name = item.get_class_name() %}
        {%- if item.is_active(admin_view) %}
        <li class="active{% if class_name %} {{class_name}}{% endif %}">
        {%- else %}
        <li{% if class_name %} class="{{class_name}}"{% endif %}>
        {%- endif %}
          <a href="{{ item.get_url() }}"{% if item.target %} target="{{ item.target }}"{% endif %}>{{ menu_icon(item) }}{{ item.name }}</a>
        </li>
      {%- endif -%}
    {% endif -%}
  {% endfor %}
{% endmacro %}

修改为:

{% macro menu(menu_root=None) %}
  {% if menu_root is none %}{% set menu_root = admin_view.admin.menu() %}{% endif %}
  {%- for item in menu_root %}
    {%- if item.is_category() -%}
      {% set children = item.get_children() %}
      {%- if children %}
        {% set class_name = item.get_class_name() %}
        {%- if item.is_active(admin_view) %}
        <li class="active">
        {% else -%}
        <li>
        {%- endif %}
        <a href="#"><i class="fa fa-bar-chart-o fa-fw"></i> {{ item.name }}<span class="fa arrow"></span></a>
        
        <ul class="nav nav-second-level">
          {%- for child in children -%}
            {% set class_name = child.get_class_name() %}
            {%- if child.is_active(admin_view) %}
            <li class="active">
            {% else %}
            <li>
            {%- endif %}
           <a href="{{ child.get_url() }}" {% if child.target %} target="{{ child.target }}"{% endif %}>{{ menu_icon(child) }}{{ child.name }}</a>
            </li>
          {%- endfor %}
          </ul>
        </li>
      {% endif %}
    {%- else %}
      {%- if item.is_accessible() and item.is_visible() -%}
        {% set class_name = item.get_class_name() %}
        {%- if item.is_active(admin_view) %}
        <li class="active{% if class_name %} {{class_name}}{% endif %}">
        {%- else %}
        <li{% if class_name %} class="{{class_name}}"{% endif %}>
        {%- endif %}
        <a href="{{ item.get_url() }}"{% if item.target %} target="{{ item.target }}"{% endif %}><i class="fa fa-dashboard fa-fw"></i> {{ menu_icon(item) }}{{ item.name }}</a>
        </li>
      {%- endif -%}
    {% endif -%}
  {% endfor %}
{% endmacro %}

主要是根据模板的菜单样式进行修改。

修改之后修改

mybase.html 把所有应的base.html 拿过来修改:


{% block head_css %} {% endblock %}


增加

<!-- MetisMenu CSS -->
<link href="{{ url_for('static', filename='vendor/metisMenu/metisMenu.min.css')}}" rel="stylesheet">
<!-- Custom CSS -->
<link href="{{ url_for('static',
filename='dist/css/sb-admin-2.css')}}" rel="stylesheet">
 <!-- Custom Fonts -->
<link href="{{ url_for('static', filename='vendor/font-awesome/css/font-awesome.min.css')}}" rel="stylesheet" type="text/css">

对于body标签下面的代码,全部黏贴来之模板的内容,
在菜单地方黏贴:
{% block menu_links %}
   {{ layout.menu_links() }}
{% endblock %}

在容器的地方黏贴:

<div id="page-wrapper">
 <!--
            <div class="row">
                <div class="col-lg-12">
                  <h1 class="page-header">Dashboard</h1>
                </div>
            </div>
-->
         <div class="row">
          {% block access_control %}
            {% endblock %}
         {% block messages %}
           {{ layout.messages() }}
          {% endblock %}
          {# store the jinja2 context for form_rules rendering logic #}
         {% set render_ctx = h.resolve_ctx() %}
         </div>
         <div class="row">
         {% block body %}{% endblock %}
         </div>
        </div>

最后的代码就如下:

{% import 'admin/mylayout.html' as layout with context -%}
{% import 'admin/static.html' as admin_static with context %}
<!DOCTYPE html>
<html>
  <head>
    <title>{% block title %}{% if admin_view.category %}{{ admin_view.category }} - {% endif %}{{ admin_view.name }} - {{ admin_view.admin.name }}{% endblock %}</title>
    {% block head_meta %}
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="AI在线 - 博客体">
        <meta name="author" content="ouyangm">
        <link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon">
        <link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon">
    {% endblock %}
    {% block head_css %}
        <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/swatch/{swatch}/bootstrap.min.css'.format(swatch=config.get('FLASK_ADMIN_SWATCH', 'default')), v='3.3.5') }}" rel="stylesheet">
        {%if config.get('FLASK_ADMIN_SWATCH', 'default') == 'default' %}
        <link href="{{ admin_static.url(filename='bootstrap/bootstrap3/css/bootstrap-theme.min.css', v='3.3.5') }}" rel="stylesheet">
        {%endif%}
        <link href="{{ admin_static.url(filename='admin/css/bootstrap3/admin.css', v='1.1.1') }}" rel="stylesheet">
          <!-- MetisMenu CSS -->
      <link href="{{ url_for('static', filename='vendor/metisMenu/metisMenu.min.css')}}" rel="stylesheet">
      <!-- Custom CSS -->
      <link href="{{ url_for('static',
      filename='dist/css/sb-admin-2.css')}}" rel="stylesheet">
       <!-- Custom Fonts -->
      <link href="{{ url_for('static', filename='vendor/font-awesome/css/font-awesome.min.css')}}" rel="stylesheet" type="text/css">
        {% if admin_view.extra_css %}
          {% for css_url in admin_view.extra_css %}
            <link href="{{ css_url }}" rel="stylesheet">
          {% endfor %}
        {% endif %}
        <style>
        body {
            padding-top: 4px;
        }
        </style>
    {% endblock %}
    {% block head %}
    {% endblock %}
    {% block head_tail %}
    {% endblock %}
  </head>
  <body>
    <div id="wrapper">

        <!-- Navigation -->
        <nav class="navbar navbar-default navbar-static-top" role="navigation" style="margin-bottom: 0">
            <div class="navbar-header">

                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/index.html"> AI在线 - 博客体 </a>
            </div>
            <!-- /.navbar-header -->

            <ul class="nav navbar-top-links navbar-right">
                <li class="dropdown">
                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                         <i class="fa fa-tasks fa-fw"></i> <i class="fa fa-caret-down"> 扩展功能 </i>
                    </a>
                    <!--
                     <ul class="dropdown-menu dropdown-user">
                        <li><a href="#"><i class="fa fa-user fa-fw"></i> User Profile</a>
                        </li>
                        <li><a href="#"><i class="fa fa-gear fa-fw"></i> Settings</a>
                        </li>
                        <li class="divider"></li>
                        <li><a href="login.html"><i class="fa fa-sign-out fa-fw"></i> Logout</a>
                        </li>
                    </ul>
                    -->
                     {% block menu_links %}
                        {{ layout.menu_links() }}
                     {% endblock %}
                    <!-- /.dropdown-messages -->
                </li>
                <!-- /.dropdown -->
                <li class="dropdown">
                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                         <i class="fa fa-envelope fa-fw"></i> <i class="fa fa-caret-down"> </i>
                    </a>
                    <ul class="dropdown-menu dropdown-tasks">
                        <li>
                            <a href="#">
                                <div>
                                    <p>
                                        <strong>Task 1</strong>
                                        <span class="pull-right text-muted">40% Complete</span>
                                    </p>
                                    <div class="progress progress-striped active">
                                        <div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%">
                                            <span class="sr-only">40% Complete (success)</span>
                                        </div>
                                    </div>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a class="text-center" href="#">
                                <strong>See All Tasks</strong>
                                <i class="fa fa-angle-right"></i>
                            </a>
                        </li>
                    </ul>
                    <!-- /.dropdown-tasks -->
                </li>
                <!-- /.dropdown -->
                <li class="dropdown">
                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                        <i class="fa fa-bell fa-fw"></i> <i class="fa fa-caret-down"></i>
                    </a>
                    <ul class="dropdown-menu dropdown-alerts">
                        <li>
                            <a href="#">
                                <div>
                                    <i class="fa fa-comment fa-fw"></i> New Comment
                                    <span class="pull-right text-muted small">4 minutes ago</span>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a href="#">
                                <div>
                                    <i class="fa fa-twitter fa-fw"></i> 3 New Followers
                                    <span class="pull-right text-muted small">12 minutes ago</span>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a href="#">
                                <div>
                                    <i class="fa fa-envelope fa-fw"></i> Message Sent
                                    <span class="pull-right text-muted small">4 minutes ago</span>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a href="#">
                                <div>
                                    <i class="fa fa-tasks fa-fw"></i> New Task
                                    <span class="pull-right text-muted small">4 minutes ago</span>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a href="#">
                                <div>
                                    <i class="fa fa-upload fa-fw"></i> Server Rebooted
                                    <span class="pull-right text-muted small">4 minutes ago</span>
                                </div>
                            </a>
                        </li>
                        <li class="divider"></li>
                        <li>
                            <a class="text-center" href="#">
                                <strong>See All Alerts</strong>
                                <i class="fa fa-angle-right"></i>
                            </a>
                        </li>
                    </ul>
                    <!-- /.dropdown-alerts -->
                </li>
                <!-- /.dropdown -->
                <li class="dropdown">
                    <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                        <i class="fa fa-user fa-fw"></i> <i class="fa fa-caret-down"></i>
                    </a>
                    <ul class="dropdown-menu dropdown-user">
                        <li><a href="#"><i class="fa fa-user fa-fw"></i> User Profile</a>
                        </li>
                        <li><a href="#"><i class="fa fa-gear fa-fw"></i> Settings</a>
                        </li>
                        <li class="divider"></li>
                        <li><a href="/admin/loginout"><i class="fa fa-sign-out fa-fw"></i> Logout</a>
                        </li>
                    </ul>
                    <!-- /.dropdown-user -->
                </li>
                <!-- /.dropdown -->
            </ul>
            <!-- /.navbar-top-links -->

            <div class="navbar-default sidebar" role="navigation">
                <div class="sidebar-nav navbar-collapse">
                    <ul class="nav" id="side-menu">
                        <li class="sidebar-search">
                            <div class="input-group custom-search-form">
                                <input type="text" class="form-control" placeholder="Search...">
                                <span class="input-group-btn">
                                <button class="btn btn-default" type="button">
                                    <i class="fa fa-search"></i>
                                </button>
                            </span>
                            </div>
                            <!-- /input-group -->
                        </li>

                  {% block main_menu %}
                   {{ layout.menu() }}
                   {% endblock %}
                   <!-- /.nav-second-level
                        <li>
                            <a href="index.html"><i class="fa fa-dashboard fa-fw"></i> Dashboard</a>
                        </li>
                        <li>
                            <a href="#"><i class="fa fa-bar-chart-o fa-fw"></i> Charts<span class="fa arrow"></span></a>
                            <ul class="nav nav-second-level">
                                <li>
                                    <a href="flot.html">Flot Charts</a>
                                </li>
                                <li>
                                    <a href="morris.html">Morris.js Charts</a>
                                </li>
                            </ul>

                        </li>
                  -->
                    </ul>
                </div>
                <!-- /.sidebar-collapse -->
            </div>
            <!-- /.navbar-static-side -->
        </nav>






        <div id="page-wrapper">
 <!--
            <div class="row">
                <div class="col-lg-12">
                  <h1 class="page-header">Dashboard</h1>
                </div>
            </div>
-->
         <div class="row">
          {% block access_control %}
            {% endblock %}
         {% block messages %}
           {{ layout.messages() }}
          {% endblock %}
          {# store the jinja2 context for form_rules rendering logic #}
         {% set render_ctx = h.resolve_ctx() %}
         </div>
         <div class="row">
         {% block body %}{% endblock %}
         </div>
        </div>
        <!-- /#page-wrapper -->

    </div>





   {% block tail_js %}
    <script src="{{ admin_static.url(filename='vendor/jquery.min.js', v='2.1.4') }}" type="text/javascript"></script>
    <script src="{{ admin_static.url(filename='bootstrap/bootstrap3/js/bootstrap.min.js', v='3.3.5') }}" type="text/javascript"></script>
    <script src="{{ admin_static.url(filename='vendor/moment.min.js', v='2.9.0') }}" type="text/javascript"></script>
    <script src="{{ admin_static.url(filename='vendor/select2/select2.min.js', v='3.5.2') }}" type="text/javascript"></script>
    <!-- sb-admin-theme  -->
    <script src="{{ url_for('static', filename='vendor/metisMenu/metisMenu.min.js') }}"></script>
   <script src="{{ url_for('static', filename='dist/js/sb-admin-2.js') }}"></script>
    <!-- Metis Menu Plugin JavaScript -->
    {% if admin_view.extra_js %}
      {% for js_url in admin_view.extra_js %}
        <script src="{{ js_url }}" type="text/javascript"></script>
      {% endfor %}
    {% endif %}
    {% endblock %}

    {% block tail %}
    {% endblock %}
  </body>
</html>

展示出来的样式:


clipboard.png