Code in block is not always executed when extended from base.html

Hi everyone,

I have an error that is occuring for months but I can’t understand why it is happening.

I have a base.html file and some html files (home.html, search.html) that extend from the base file. The base file consists of a footer menu with several links to the extended pages.

Something like this:

  <div id="footer-menu">
      <a href="{% url 'home' %}" >Home</a>
      <a href="{% url 'search' %}" >Search</a>
 </div>

The base.html also contains a block scripts at the end of the body tag({% block scripts %}{% endblock %}). There is nothing within the block here.

In home.html & search.html I am putting some logic into the scripts block.

The problem now is that when I switch between views, the code of the scripts block is not always executed. In my views.py I added @never_cache, but this doesn’t help.

Is this a bug with extends? Or am I doing something wrong?

Thanks a lot!

You’re probably doing something wrong. Each page is rendered independently of any other.

For us to diagnose this, we’ll need to see the complete template being rendered, the template being extended, and the view that is rendering the template incorrectly. (That’s just to get started - depending upon what’s being done, we may end up needing to see the models along with some other information.)

When you copy code into the forum, place it between lines consisting of only three backtick - ` characters. This means you’ll have a line that is only ```, followed by your code, followed by another line of ```. Make sure you use the backtick - ` and not the apostrophe - '.

Ken

base.html

<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://cdn.lr-ingest.io/LogRocket.min.js" crossorigin="anonymous"></script>
  <script>window.LogRocket && window.LogRocket.init('hmfxwj/smartendr');</script>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
  <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, viewport-fit=cover" />
  <title>Smartendr | The virtual bartender</title>
  <link async href="https://fonts.googleapis.com/css?family=Poppins:400,500,700" rel="stylesheet">
  {% load static %}
  {% load i18n %}
  <link rel="stylesheet" type="text/css" href="{% static 'orders/css/framework-new.css' %}">
  {% block headers %}{% endblock %}
</head>

<body class="theme-light" data-background="none" data-highlight="{{main_color}}">
  <div id="page">
    <div id="page-preloader">
      <div class="loader-main" id="loader-main">
        <div class="preload-spinner preload-medium border-highlight"></div>
      </div>
    </div>
    {% block menu %}{% endblock %}

    <div id="footer-menu" class="footer-menu-5-icons footer-menu-style-1 shadow-huge">
      <a href="{% url 'home3' %}" class="{% if tab == 'home' %}active-nav{% endif %}">
        <i class="fa fa-home"></i>
        <span>{% trans "Home" %}</span>
      </a>
      <a href="{% url 'search3' %}" class="{% if tab == 'search' %}active-nav{% endif %}">
        <i class="fa fa-search"></i>
        <span>{% trans "Search" %}</span>
      </a>
      <a href="{% url 'cart3' %}" class="{% if tab == 'cart' %}active-nav{% endif %}" id="menu-cart">
        <i class="fas fa-shopping-cart" style="position:relative">
          <span class="badge"
            style="color:white;background-color:{{main_color_hex}};left:13px;width:20px;height:20px;top:4px;border-radius:10px;overflow:hidden;padding:0;line-height:20px;font-weight:bold;text-align:center;">[[amount_of_items]]</span>
        </i>
        <span>{% trans "Cart" %}</span>
      </a>
      <a href="{% url 'like' %}" class="{% if tab == 'like' %}active-nav{% endif %}">
        <i class="far fa-heart"></i>
        <span>{% trans "Community" %}</span>
      </a>
      <a href="{% url 'settings' %}" class="{% if tab == 'settings' %}active-nav{% endif %}">
        <i class="fas fa-ellipsis-h"></i>
        <span>{% trans "More" %}</span>
      </a>
      <div class="clear"></div>
    </div>
    <div class="page-content header-clear-medium" id="page-content" style="background:white">
      {% block content %}{% endblock %}
    </div>
    {% block aftercontent %}{% endblock %}
  </div>
  <script type="text/javascript" src="{% static 'orders/js/jquery.js' %}"></script>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script type="text/javascript" src="{% static 'orders/js/plugins.js' %}"></script>
  <script type="text/javascript" src="{% static 'orders/js/custom.js' %}"></script>
  {% block scripts %}{% endblock %}
</body>
</html>

cart.html

{% extends "orders/menu_base_new.html" %}

{% load static %}
{% load i18n %}


{% block headers %}
<style>
  body {
    font-family: 'Poppins', sans-serif !important;
  }
  .mb-3 {
    margin-bottom: 24px !important;
  }
  .section.full {
    padding: 0;
  }
  .mt-2 {
    margin-top: 16px !important;
  }
  .section.full .section-title {
    padding-left: 16px;
    padding-right: 16px;
  }
  .mb-1 {
    margin-bottom: 8px !important;
  }
  .section-title {
    font-size: 15px;
    padding: 6px 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: #141515;
    font-weight: 500;
  }

  .no-js .owl-carousel,
  .owl-carousel.owl-loaded {
    display: block;
  }

  .carousel-multiple {
    width: calc(100% + 16px);
    margin-left: -16px;
  }

  .owl-carousel {
    display: none;
    width: 100%;
    z-index: 1;
  }

  .owl-carousel,
  .owl-carousel .owl-item {
    -webkit-tap-highlight-color: transparent;
    position: relative;
  }

  .card {
    background: #ffffff;
    border-radius: 6px;
    border: 0;
    box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.1), 0 1px 3px 0 rgba(0, 0, 0, 0.08);
  }

  .card-body {
    -ms-flex: 1 1 auto;
    flex: 1 1 auto;
    min-height: 1px;
    padding: 1.25rem;
  }
</style>

{% endblock %}

{% block menu %}
<div class="header header-fixed header-logo-left">
  <a href="" class="header-title" style="font-weight:500;font-family: 'Poppins', sans-serif;font-size:17px;line-height:40px">{% trans "My cart"|title %}
    <span style="display:block;padding:0px;margin:0px;line-height:0px;font-size:12px; color:grey;font-family: 'Poppins', sans-serif">{{settings.display_name}} x Smartendr</span>
  </a>
  <a href="{% url 'empty_cart' %}" class="header-icon header-icon-1"><i class="fa fa-trash" style="font-size: 1.5em;color:{{secondary_color_hex}}"></i></a>
</div>
{% endblock %}

{% block content %}


<form id="form-id" method="post">
  {% csrf_token %}

<div class="content-boxed content-boxed-full" style="margin: 10px 0px 30px 0px;border-radius:0px !important;border-bottom: solid 1px rgba(0,0,0,0.15);border-top: solid 1px rgba(0,0,0,0.15);">
      <div class="link-list link-list-1" style="border-bottom: solid 0px rgba(0,0,0,0.05);">
          <a href="#">
              <i class="fas fa-money-check bg-fade-{{secondary_color}}-dark round-huge color-white-dark" style="left:5px"></i>
              <span style="font-weight:400;font-family: 'Poppins', sans-serif;font-size:16px;margin-left:55px">
                <select id="payment" style='all:unset; {% if payment_methods|length > 1 %}%appearance:menulist;-webkit-appearance: menulist;-moz-appearance: menulist;{% endif %}' name='payment_method'>
                  {% for payment in payment_methods %}
                  <option value="{{payment.name}}" {% if payment.name == 'RM' %}data-menu="menu-service"{% endif %}>{{payment.get_name_display}}</option>
                  {% endfor %}
                </select>
              </span>
          </a>
        </div>
</div>


  <div class="content-boxed" style="margin: 30px 0px 30px 0px;border-radius:0px !important;border-bottom: solid 1px rgba(0,0,0,0.15);border-top: solid 1px rgba(0,0,0,0.15);">
    <div class="content bottom-5">
      <h3 style="font-family: 'Poppins', sans-serif;font-weight:500">Items</h3>
      <div class="link-list link-list-1">
        <a href="javascript:void(0)" data-menu="menu-task-group" class="cartProduct" id="cartProduct" name="{{item.0}}" value="">
          <i class="" style="top:0px;line-height:50px;font-style:normal;color:#ea5d0f">{{item.2}} x</i>
          <span>
            <h5 style="line-height:inherit;margin-bottom:-10px;font-family: 'Poppins', sans-serif;font-weight:400">{{item.1}}</h5>

          </span>
          <i class="" style="top:0px;line-height:50px">{{item.3}}€</i>
        </a>

        <a href="#" id="cartProduct">
          <i class="" style="top:0px;line-height:50px;font-style:normal;color:black;font-family: 'Poppins', sans-serif;">{% trans "Total" %}</i>
          <span>&nbsp;</span>
          <i class="" style="top:0px;line-height:50px;font-weight:900;font-style:normal;font-size:12px;width:30px">€</i>
        </a>
      </div>
    </div>
  </div>

  {% if upselling %}
  <div class="section full mt-2 mb-3">
    <h3 style="font-family: 'Poppins', sans-serif;font-weight:500; font-size:14px;padding:10px">Populair bij soortgelijke bestellingen</h3>
    <div class="carousel-multiple owl-carousel owl-theme">
      <div v-for="product in products" class="item">
        <div class="card product-card">
          <div class="card-body">
            <h2 class="title">[[product.name]]</h2>
            <div class="price">[[product.price]]€ - [[product.category_name]]</div>
            <a href="#" class="btn btn-sm btn-block" style="background-color:#ea5d0f;color:white">ADD TO CART</a>
          </div>
        </div>
      </div>
    </div>
  </div>
  {% endif %}

  {% if tip %}
  <div class="content-boxed" style="margin: 30px 0px 30px 0px;border-radius:0px !important;border-bottom: solid 1px rgba(0,0,0,0.15);border-top: solid 1px rgba(0,0,0,0.15);">
    <input type="number" min="0" max="100" step="5">
  </div>
  {% endif %}
  <!-- <div class="fac fac-checkbox-round fac-default" style="margin:20px"><span></span>
    <input id="box1-fac-checkbox-round" type="checkbox" value="1" checked="">
    <label for="box1-fac-checkbox-round" style="font-size:8px;padding-left:2rem">I acknowledge & agree that processing of aggregated/pseudonimyzed data by the f&b partners of Smartendr for the purpose of analyzing/improving falls within the
      legitimate interest of Smart Online and its commercial partners for processing such data.</label>
  </div> -->

  <button onClick="this.disabled=true;this.form.submit()" class="button button-margins button-m button-full button-round-small shadow-medium" id="order-button-cart"
    style="background-color:#27A744;width: 90%;padding: 16px !important;font-size: 16px;z-index:98">{% trans "Order" %}</button>
    <!-- <button onClick="this.disabled=true;this.form.submit()" class="button button-margins button-m button-full button-round-small shadow-medium"
      style="background-color:#27A744;bottom: calc(65px + (env(safe-area-inset-bottom))*1.1);position: fixed;width: 90%;padding: 16px !important;font-size: 16px;z-index:98">{% trans "Order" %}</button> -->

  <!-- <a href="javascript:void(0)" id="makeOrder" class="button button-margins button-m button-full button-round-small shadow-medium"
    style="background-color:#27A744;bottom: calc(65px + (env(safe-area-inset-bottom))*1.1);position: fixed;width: 90%;padding: 16px !important;font-size: 16px;">{% trans "Order" %}</a> -->
  <!-- <a href="#" data-menu="menu-confirm" class="button button-margins button-m button-full button-round-small shadow-medium bottom-30" style="background-color:#27A744">{% trans "Order" %}</a> -->
</form>
{% endblock %}

{% block aftercontent %}
<!--Menu Task Group-->
<div id="menu-task-group" class="menu menu-box-bottom menu-box-detached round-large" data-menu-height="250" data-menu-effect="menu-over">
  <div class="content bottom-0 top-20">
    <h1 class="center-text bolder" id="nameOfCartProduct" name=""></h1>
    <p class="center-text under-heading font-10"></p>
    <div class="one-third last-column center-text">
      <a href="javascript:void(0)" id="changeQuantity" name="decrement" class="icon icon-l bg-green1-fade round-huge"><i class="fa fa-minus color-red2-dark bg-fade-red2-dark"></i></a>
      <!-- <h4 class="bolder">5</h4>
            <p class="bottom-10 under-heading font-10">Incomplete Tasks</p> -->
    </div>
    <div class="one-third center-text">
      <!-- <a href="#" class="icon icon-l bg-green1-fade round-huge"><i class="fa fa-minus color-blue2-dark bg-fade-blue2-dark"></i></a> -->
      <h4 class="bolder" id="amountOfCartProduct"></h4>
      <p class="bottom-10 under-heading font-10">Aantal</p>
    </div>
    <div class="one-third center-text">
      <a href="javascript:void(0)" id="changeQuantity" name="increment" class="icon icon-l bg-green1-fade round-huge"><i class="fa fa-plus color-green1-dark bg-fade-green1-dark"></i></a>
      <!-- <h4 class="bolder">153</h4> -->
      <!-- <p class="bottom-10 under-heading font-10">Finished Tasks</p> -->
    </div>
    <div class="clear"></div>
    <div class="divider top-10 bottom-0"></div>
    <a href="javascript:void(0)" id="saveProductCart" class="top-10 bottom-10 center-text font-15" style="color:rgb(234, 93, 15)">Update</a>
  </div>
</div>

<div class="menu-hider"></div>

{% endblock %}

{% block scripts %}

<script>
console.log('menu_cart');
  var app = new Vue({
    el: '#page',
    delimiters: ['[[', ']]'],
    data: {
      selectedProduct: "",
      selectedLanguage: "nl",
      products: {{products|safe}},
      amount_of_items: 99,
    },
    filters : {

    },
    methods: {

    },
    computed: {

    },
    mounted() {
      $('.carousel-multiple').owlCarousel({
        stagePadding: 32,
        loop: true,
        margin: 16,
        nav: false,
        items: 1,
        dots: false,
        responsiveClass: true,
        responsive: {
          0: {
            items: 1,
          },
          768: {
            items: 4,
          }
        }
      });
    }
  })
</script>

{% endblock %}

menu.html

{% extends "orders/menu_base_new.html" %}
{% load static %}
{% load i18n %}
{% block headers %}
<link rel="manifest" href="{% static 'manifest.json' %}">
<style>
  .header-clear-medium {
    padding-top: 60px;
  }
  #owl-demo .item {
    margin: 3px;
  }
  #owl-demo .item img {
    display: block;
    width: 100%;
    height: auto;
  }
  {% if view_only %}
  #footer-menu{
    visibility: hidden;
  }
  {% endif %}
</style>
{% endblock %}

{% block menu %}

<div class="header header-fixed header-logo-left">
  <a href="javascript:void(0)" class="header-title" style="font-weight:500;font-family: 'Poppins', sans-serif;letter-spacing: -0.05rem;{% if display_name|length > 11 %}font-size:14px;{% else %}font-size:19px;{% endif %}">
    <img src="{% if logo %}{{logo}}{% else %}{% static 'venues/media/logo-simple.png' %}{% endif %}" style="all:unset;width:20px;vertical-align:middle;border-radius:5px;margin-right:5px" />
    {{display_name}}
  </a>
</div>

{% endblock %}

{% block content %}

<h3 style="font-family: 'Poppins', sans-serif;font-weight:500; font-size:20px;padding:10px">{% trans "Categories" %}</h3>

<div v-for="(column, index) in chunkedItems" class="blog-categories blog-categories-2 small-bottom">
  <a v-for="(item, index) in column" href="javascript:void(0)" :data-toggle-box="'archive-box-'+item.id">
    {% if show_category %}<em style="font-weight:600;font-family: 'Poppins', sans-serif;font-size:20px;">[[ item.name ]]</em>{% endif %}
    <span style="opacity:0.1;border-radius: 10px;background-color:#000000 !important" ></span>
    <picture class="preload-image responsive-image" alt="img">
      <source :srcset="[[ item.image]]" type="image/webp">
      <source :srcset="[[ item.image]]" type="image/png">
      <img :src="[[ item.image]]" class="preload-image responsive-image" alt="img">
    </picture>
  </a>

  <div v-for="(item, index) in column" class="archive-box-content" :id="'archive-box-'+item.id">
    <table class="table-borders-dark" style="margin:5px;padding:5px">
      <tr>
        <th colspan="3" style="background-color:#F8F5F2">
          <h2 style="text-align:center;font-weight:500;font-family: 'Poppins', sans-serif;font-size:18px;">[[item.name]]</h2>
        </th>
      </tr>
      <tr v-for="product in item.products" style="border-bottom:1pt solid black">
        <td style="border-bottom:1pt solid #DCDCDC;text-align:left;vertical-align:middle;width:60%;padding:5px" v-bind:style="product.added?'border-left: 2pt solid {{main_color_hex}}': ''">
          <a v-on:click.stop.prevent="selectProduct(product)" name="[[product.id]]" title="[[product.name]]" value="[[product.id]]" id="productInfo" data-menu="menu-product"
            style="font-size:16px;font-weight:500;font-family: Poppins, sans-serif;text-decoration:none;color:black;padding:0;margin:0;width:100%">[[product.name|truncatechars:25]]
            <!-- <i class="fas fa-info-circle fa-xs"></i>-->
          </a>[[product.description]]
        </td>
        <td class="" style="padding:5px;border-bottom:1pt solid #DCDCDC;vertical-align:middle;width:30%;font-size:14px;font-weight:600;font-family: Poppins, sans-serif;">[[product.price]]€</td>
        <td style="vertical-align:middle;border-bottom:1pt solid #DCDCDC;width:33%;margin:10px">
          {% if not view_only %}
          <a v-on:click.stop.prevent="addToCart(product)" class="btn btn-sm btn-block fa fa-plus rotate-270"
            style="font-size:15px;width:95%;text-align:center;padding-left:20px;padding-right:20px;background-color: #ea5d0f;color:white;border-radius:5px"></a>
          {% endif %}
        </td>
      </tr>
    </table>
  </div>

</div>

{% endblock %}

{% block aftercontent %}

<!-- Added to Cart-->
<div id="menu-added" class="menu menu-box-modal" data-menu-hide="800" data-menu-width="250" data-menu-height="150" style="border-radius: 20px!important;">
  <h1 class="text-center mt-3 pt-2" style="padding-top: .625rem!important;margin-top:.9375rem!important;">
    <i class="fa fa-check-circle color-green-dark fa-3x" style="color: #8cc152!important;"></i>
  </h1>
  <h3 class="text-center pt-2" style="padding-top: .625rem!important;font-size:20px;line-height:24px;font-weight:700">{% trans 'Added to order' %}</h3>
</div>

<div class="menu-hider {% if explanation %}menu-active{% endif %}"></div>

{% endblock %}

{% block scripts %}


<script>
  axios.defaults.xsrfCookieName = 'csrftoken'
  axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"

  var app = new Vue({
    el: '#page',
    delimiters: ['[[', ']]'],
    data: {
      items: {{items|safe}},
      amount_of_items: {{amount_of_items}},
      selectedProduct: "",
      selectedLanguage: "nl",
    },
    filters : {

    },
    methods: {
      chunk (arr,len) {
        var chunks = [];
        var i = 0;
        var n = arr.length;
        while(i<n) {
          chunks.push(arr.slice(i, i += len));
        }
        return chunks;
      },
      addToCart(product){
        $('#menu-added').addClass("menu-active");
        $('.menu-hider').addClass('menu-active');
        setTimeout(function() {
          $('#menu-added').removeClass("menu-active");
          $('.menu-hider').removeClass('menu-active');
        }, 1000);
        this.amount_of_items += 1;
        product.added = true;
        axios.post('{% url "api_add_to_cart" %}', {'product': product});
      },
      selectProduct(product){
        this.selectedProduct = product;
      },
      selectCategory(category){
        category.selected = true;
      },
      selectLanguage(language){
        this.selectedLanguage = language;

      }
    },
    computed: {
      activeCategories() {
        return this.items.filter(item => {
          return !item.deleted;
        });
      },
      chunkedItems() {
        return this.chunk(this.sortedItems, 2)
      },
      sortedItems(){
        function compare(a, b) {
          if (a.name < b.name)
            return -1;
          if (a.name > b.name)
            return 1;
          return 0;
        }

        return this.items.sort(compare);
      }
    },
    mounted() {
      $(".owl-slider4").owlCarousel({
        stagePadding: 10,
        loop: false,
        margin: 15,
        nav: false,
        items: 5,
        dots: false,
        responsiveClass: true,
        responsive: {
          0: {
            items: 5,
          },
          768: {
            items: 8,
          }
        }
      });
    }
  })
</script>
{% endblock %}

The views are just renders (render(request, ‘menu.html’, {context}).

Thanks a lot for you time and effort. Reallly appreciated!

For clarification, are you saying that both views sometimes work and sometimes fail? Or is it that one always works and the other fails?

(You didn’t mention that vue was involved - I’m not sure if or how that will affect this yet.)

Does anything show up in the browser’s console for those pages that fail?

Debugging this may just involve chasing down what’s happening in the browser - can’t tell yet.

Oh, and the reason that I requested to see the views is to determine whether or not the context being rendered might be part of the problem. You’re rendering at least one django variable within the context of the scripts, and so if what’s rendered is invalid JavaScript, that could cause the script to fail.

Generally speaking, I don’t like to render the JavaScript code itself. I prefer passing usable variables to my JS functions through variables rendered with the json_script filter.

Ken

Hi Ken,

Thanks for your response!

The views work independently: so when I go to the home url or search url immediately it is working (because everything is loaded I think). But when I navigate with the footer menu from one page to another, the JS code is not always executed. I think some kind of caching in the blocks. When I do for example a console.log(’’) in the script block, the log is not always executed.

The context is rendered correctly, so this is not a thing.

Vue.js has nothing to do with, because I had this problem even before i was making use of Vue.js so this is not the problem.

Thanks!

I do not see where you’ve included either {% load cache %} or {% cache %} in either of your templates, so Django’s block caching shouldn’t be involved. If you’re still concerned about that, you can try it with your cache disabled.

Are you seeing any JavaScript_ errors in your browser’s console log? Are any errors showing up in the console where you’re running Django?

Sometimes I have GET http://localhost:8000/kiosk/null in my console when clicking on an item in the footer menu. Kiosk is the name of my application. I don’t understand why it is taking /null. But I don’t know if this has something to do with the scripts block.

Might all be part of the bigger picture. But I think at this point you’ll need to take a very detailed look at exactly what has been rendered and sent to the browser. I’m guessing that something isn’t being rendered the way you’re expecting it to be. But I can’t tell that for sure in the absence of a lot more detailed information.

Keep in mind that the entire page is rendered on the server side before being sent to the browser. Once it’s returned as an HTTP response, there isn’t anything like “blocks” or “templates” that still exist. It’s all one page. Since these scripts are being rendered as text within the page, it’s not possible for the browser to be caching them independently of the remainder of that page. If the javascript isn’t running, there’s something wrong in the javascript.

I will dig deeper into it. Thanks a lot for your insights!