pallets-eco / flask-admin

Simple and extensible administrative interface framework for Flask
https://flask-admin.readthedocs.io
BSD 3-Clause "New" or "Revised" License
5.8k stars 1.58k forks source link

Custom edit/list/view templates are getting improperly rendered HTML #1934

Open servitor-io opened 5 years ago

servitor-io commented 5 years ago

Supplying a custom template like:

{% extends 'admin/model/create.html' %}

{% block body %}
    {{ super() }}
{% endblock %}

and then passing these templates in the ModelView subclass like:


class RosterView(ModelView):
    list_template = 'web/roster_list.html.jinja'
    create_template = 'web/roster_create.html.jinja'
    edit_template = 'web/roster_edit.html.jinja'

    column_list = ['name', 'player_name', 'factions', 'entries', 'users', 'points']
    column_editable_list = ['name', 'player_name', 'factions', 'entries', 'users']

The HTML doesn't get properly rendered, the resulting source looks like:


<!DOCTYPE html>
<html>
  <head>
    <title>Roster - Roster - Admin</title>

        <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="">
        <meta name="author" content="">

        <link href="/admin/static/bootstrap/bootstrap2/swatch/default/bootstrap.min.css?v=2.3.2" rel="stylesheet">
        <link href="/admin/static/bootstrap/bootstrap2/css/bootstrap-responsive.css?v=2.3.2" rel="stylesheet">
        <link href="/admin/static/admin/css/bootstrap2/admin.css?v=1.1.1" rel="stylesheet">

        <style>
        body {
            padding-top: 4px;
        }
        </style>

  &lt;link href=&#34;/admin/static/vendor/select2/select2.css?v=3.5.2&#34; rel=&#34;stylesheet&#34;&gt;
  &lt;link href=&#34;/admin/static/vendor/bootstrap-daterangepicker/daterangepicker-bs2.css?v=1.3.22&#34; rel=&#34;stylesheet&#34;&gt;

  &lt;link href=&#34;/admin/static/vendor/x-editable/css/bootstrap2-editable.css?v=1.5.1.1&#34; rel=&#34;stylesheet&#34;&gt;

  </head>
  <body>

    <div class="container">
      <div class="navbar">
        <div class="navbar-inner">

          <a class="brand" href="/admin">Admin</a>

          <ul class="nav">

        &lt;li&gt;
          &lt;a href=&#34;/admin/&#34;&gt;Home&lt;/a&gt;
        &lt;/li&gt;
        &lt;li class=&#34;dropdown&#34;&gt;
          &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;

            Pieces&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
          &lt;ul class=&#34;dropdown-menu&#34;&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/figure/&#34;&gt;
              Figure&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/wargear/&#34;&gt;
              Wargear&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;

        &lt;li class=&#34;dropdown&#34;&gt;
          &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;

            Metadata&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
          &lt;ul class=&#34;dropdown-menu&#34;&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/keyword/&#34;&gt;
              Keyword&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/faction/&#34;&gt;
              Faction&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;

        &lt;li class=&#34;dropdown&#34;&gt;
          &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;

            Rules&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
          &lt;ul class=&#34;dropdown-menu&#34;&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/ability/&#34;&gt;
              Ability&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/specialization/&#34;&gt;
              Specialization&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/tactic/&#34;&gt;
              Tactic&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;

        &lt;li class=&#34;active dropdown&#34;&gt;

          &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;

            Roster&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
          &lt;ul class=&#34;dropdown-menu&#34;&gt;

              &lt;li class=&#34;active&#34;&gt;

              &lt;a href=&#34;/admin/roster/&#34;&gt;
              Roster&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/rosterentry/&#34;&gt;
              Roster Entry&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;

        &lt;li class=&#34;dropdown&#34;&gt;
          &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;

            User&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
          &lt;ul class=&#34;dropdown-menu&#34;&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/user/&#34;&gt;
              User&lt;/a&gt;
              &lt;/li&gt;

              &lt;li&gt;
              &lt;a href=&#34;/admin/role/&#34;&gt;
              Role&lt;/a&gt;
              &lt;/li&gt;
          &lt;/ul&gt;
        &lt;/li&gt;

          </ul>

          <ul class="nav pull-right">

          </ul>

        </div>
      </div>

    <ul class="nav nav-tabs actions-nav">
        <li class="active">
            <a href="javascript:void(0)">List</a>
        </li>

        <li>
            <a href="/admin/roster/new/?url=%2Fadmin%2Froster%2F" title="Create New Record">Create</a></li>

        <li class="dropdown">
            &lt;a class=&#34;dropdown-toggle&#34; data-toggle=&#34;dropdown&#34; href=&#34;javascript:void(0)&#34;&gt;With selected&lt;b class=&#34;caret&#34;&gt;&lt;/b&gt;&lt;/a&gt;
    &lt;ul class=&#34;dropdown-menu&#34;&gt;

        &lt;li&gt;
            &lt;a href=&#34;javascript:void(0)&#34; onclick=&#34;return modelActions.execute(&#39;delete&#39;);&#34;&gt;Delete&lt;/a&gt;
        &lt;/li&gt;

    &lt;/ul&gt;

        </li>

    </ul>

    <div id="no-more-tables">
    <table class="table table-striped table-bordered table-hover model-list cf">
        <thead class="cf">
            <tr>

                    <th class="list-checkbox-column">
                        <input type="checkbox" name="rowtoggle" class="action-rowtoggle" title="Select all records" />
                    </th>

                        <th class="span1">&nbsp;</th>

                    <th class="column-header col-name">

                                <a href="/admin/roster/?sort=0" title="Sort by Name">Name</a>

                    </th>

                    <th class="column-header col-player_name">

                                <a href="/admin/roster/?sort=1" title="Sort by Player Name">Player Name</a>

                    </th>

                    <th class="column-header col-factions">

                            Factions

                    </th>

                    <th class="column-header col-entries">

                            Entries

                    </th>

                    <th class="column-header col-users">

                            Users

                    </th>

                    <th class="column-header col-points">

                            Points

                    </th>

            </tr>
        </thead>

        <tr>
            <td colspan="999">

                <div class="text-center">
                    There are no items in the table.
                </div>

            </td>
        </tr>

    </table>
    </div>

    &lt;form id=&#34;action_form&#34; action=&#34;/admin/roster/action/&#34; method=&#34;POST&#34; style=&#34;display: none&#34;&gt;

        &lt;input id=&#34;url&#34; name=&#34;url&#34; type=&#34;hidden&#34; value=&#34;/admin/roster/&#34;&gt;
        &lt;input id=&#34;action&#34; name=&#34;action&#34; type=&#34;hidden&#34; value=&#34;&#34;&gt;
    &lt;/form&gt;

    </div>

    <script src="/admin/static/vendor/jquery.min.js?v=3.3.1" type="text/javascript"></script>
    <script src="/admin/static/bootstrap/bootstrap2/js/bootstrap.min.js?v=2.3.2" type="text/javascript"></script>
    <script src="/admin/static/vendor/moment.min.js?v=2.22.2" type="text/javascript"></script>
    <script src="/admin/static/vendor/select2/select2.min.js?v=3.5.2" type="text/javascript"></script>

  &lt;script src=&#34;/admin/static/vendor/bootstrap-daterangepicker/daterangepicker.js?v=1.3.22&#34;&gt;&lt;/script&gt;

  &lt;script src=&#34;/admin/static/vendor/x-editable/js/bootstrap2-editable.min.js?v=1.5.1.1&#34;&gt;&lt;/script&gt;

  &lt;script src=&#34;/admin/static/admin/js/form.js?v=1.0.1&#34;&gt;&lt;/script&gt;

    <script src="/admin/static/admin/js/filters.js?v=1.0.0"></script>

        &lt;div id=&#34;actions-confirmation-data&#34; style=&#34;display:none;&#34;&gt;{&#34;delete&#34;: &#34;Are you sure you want to delete selected records?&#34;}&lt;/div&gt;
        &lt;div id=&#34;message-data&#34; style=&#34;display:none;&#34;&gt;&#34;Please select at least one record.&#34;&lt;/div&gt;
        &lt;script src=&#34;/admin/static/admin/js/actions.js?v=1.0.0&#34;&gt;&lt;/script&gt;

  </body>
</html>

And the appearance is like:

Screen Shot 2019-12-01 at 9 41 53 AM

I'm just following the example from the documentation here: https://flask-admin.readthedocs.io/en/latest/introduction/#extending-the-built-in-templates

Is there something missing to make this template customization work? When I don't try to override defaults everything appears to work correctly

celtic34fr commented 4 years ago

hi,

I've the same behavour when I try to create a custom view extending admin/master.html. All of the code inserted for the navigation (into ul tag with 'class="nav navbar-nav"' in div tag id="admin-navbar-collapse") appear as a string in my browser (Google Chrome Version 80.0.3987.149 (Build officiel) (64 bits) Window 10 Pro). I've tryed to change the reference of the template extended, but no change see at all.

I use the 1.5.5 version of Flask-Admin with bootstrap3 template mode.

celtic34fr commented 4 years ago

I tried 2 simple modifications in admin / base.html: add '| secure 'to the execution order of the macros layout.menu () and layout.menu_link () then the navigation menu appears as expected.

Can we quickly integrate this modification in order to control its effectiveness and if it does not generate any disorder effect in the rendering of pages (system or user)?

TomHall2020 commented 2 years ago

Appreciate this has been a while, but may be helpful for those searching for this problem. I had a similar issue although it was only the top navbar links that were escaped out and displaying incorrectly for me.

I was able to resolve by changing my custom template extension from .html.j2 to .html. I noticed your custom template also had the double extension .html.jinja. Not sure why the admin templating system is being picky about the file extension?

mo8it commented 2 years ago

@TomHall2020 I did have the exact same problem. Maybe we should rename the issue or open a new one about not accepting other file extension or maybe adding jinja, jinja2, j2, etc.

jjjacksn commented 2 years ago

Just had the same issue here using templates ending with .html.jinja.