Context variables not displayed when saved in the model

Hello,

I am trying to implement the render_to_string function in a Django project.

I have an HTML template (strategy.html) containing many Django Template Language variables and ‘if conditions’ and would like to save the rendered output in a DB model.

The output is saved in the db model but the context variables are ignored.

The action has to be triggered once the ‘Save’ button is clicked (see code below).

Important note: the DTL variables and ‘if conditions’ are correctly displayed when using the render function by clicking the ‘Generate’ button.

Here is the views.py file:

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.template.loader import render_to_string
from strategiesAPI.models import strategiesList


@login_required
def index(request):
    if request.method == "POST":
        # Get form information
        starttime = request.POST.get("starttime")
        endtime = request.POST.get("endtime")
        trigger = request.POST.get("trigger")
        entrieslimit = request.POST.get("entrieslimit")
        direction = request.POST.get("direction")
        pattern = request.POST.get("pattern")
        stoploss = request.POST.get("stoploss")
        takeprofit = request.POST.get("takeprofit")
        tradeliquid = request.POST.get("tradeliquid")

        # Context variables for the render and render_to_string function 
        content = {
                "starttime": starttime, 
                "endtime": endtime, 
                "trigger": trigger, 
                "entrieslimit": entrieslimit, 
                "direction": direction, 
                "pattern": pattern, 
                "stoploss": stoploss, 
                "takeprofit": takeprofit, 
                "tradeliquid": tradeliquid
                    }
        
        # Action based on the button pressed inside the index.html template

        # GENERATE button
        if request.POST['button'] == 'Generate':
            # Write strategy on the right side of the page using the user's inputs
            return render(request, "composer/index.html", content)

        # SAVE button
        if request.POST['button'] == 'Save':
            # Save the strategy DTL output into the db model using the render_to_string function
            strategy_html = render_to_string("composer/strategy.html", content)
            strategiesList.objects.create(script=strategy_html)
            return render(request, "composer/index.html")
    else:
        return render(request, "composer/index.html")

Below I will paste what is saved in the db model followed by the strategy.html file (which is part of the main page index.html) containing the DTL variables and ‘if conditions’ (which are ignored):

<!-------------------------------------- Right-side EasyLanguage & DTL output -------------------------------------->

<div class="right" id="output" style="font-size: 11px;">
    // EasyLanguage code composer by ©SOACM. All rights reserved // <br>
    <br>

    <!-------------------------------------- Breakout -------------------------------------->
    
    <!-------------------------------------- Breakout end ----------------------------------->


    <!-------------------------------------- Reversal --------------------------------------->
    
    <!-------------------------------------- Reversal end ------------------------------------->
</div>
<!-------------------------------------- Right-side EasyLanguage & DTL output -------------------------------------->

<div class="right" id="output" style="font-size: 11px;">
    // EasyLanguage code composer by ©SOACM. All rights reserved // <br>
    <br>

    <!-------------------------------------- Breakout -------------------------------------->
    {% if trigger == "breakout" %}
        input: StartTime({{ starttime }}), EndTime({{ endtime }}), MyStopLoss({{ stoploss }}), MyTakeProfit({{ takeprofit }}); <br>
        var: bool MyTime(False), int MP(0); <br>
            MP = MarketPosition; <br>
            MyTime = False; <br>
            if Time >= StartTime and Time <= EndTime and EntriesToday(date[0]) < 1 then MyTime = True; <br>
            <br>
            
            {% if pattern == "none" %}
            // Levels <br>
            if date <> date[1] then begin <br>
            var: highd1(0), lowd1(0); <br>
            highd1 = HighS(1); <br>
            lowd1 = LowS(1); <br>
            end; <br>
            {% endif %}
            <br>

Thank you in advance.

EDIT: can the issue be caused by Django’s security features like the make_safe function?

To clarify: the example HTML you show that “is saved in the db model”, have you got that by actually looking at what’s saved in the database column itself? Or is it from what you see in the browser when you then render index.html?

Copied from the model in /admin

After these lines:

If you do print(content) and print(strategy_html) what do you see in the console? I’m just trying to work out where it’s going wrong.

In general it’s a bad idea to use .get in my opinion. If there is a spelling error somewhere this will silently just assign a None to the variable. If you do request.POST["starttime"] instead you will get a nice crash at the place of the problem, instead of a silent failure.

You mix the words “content” and “context” randomly. You should stick to context for context.

You never pass the context variable to the “save” button render(). That looks suspicious to me.

You should install django-fastdev to get errors instead of silent failures in templates.

1 Like

Thank you for your response. Django-fastdev might come in handy in the future.

I have implemented all your suggestions, but the issue still persists.
I also added a print statement (line 41), but the output still does not contain the context variables.

Could render_to_string be the cause? How can I troubleshoot it?

EDIT: the correct output is now displayed. I will explain the cause in a follow-up reply. Thank you for your help!

from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from django.template.loader import render_to_string
from strategiesAPI.models import strategiesList


@login_required
def index(request):
    # Get the template info
    if request.method == "POST":
        # Get form information
        starttime = request.POST["starttime"]
        endtime = request.POST["endtime"]
        trigger = request.POST["trigger"]
        direction = request.POST["direction"]
        pattern = request.POST["pattern"]
        stoploss = request.POST["stoploss"]
        takeprofit = request.POST["takeprofit"]
        tradeliquid = request.POST["tradeliquid"]

        # Context variables for the render and render_to_string function 
        context = {
                "starttime": starttime, 
                "endtime": endtime, 
                "trigger": trigger, 
                "direction": direction, 
                "pattern": pattern, 
                "stoploss": stoploss, 
                "takeprofit": takeprofit, 
                "tradeliquid": tradeliquid
                    }
        
        # Action based on the button pressed inside the index.html template
        if request.POST['button'] == 'Generate':
            # Write strategy on the right side using the user's inputs
            return render(request, "composer/index.html", context)
        
        if request.POST['button'] == 'Save':
            # Save the strategy DTL output into the db model using the render_to_string function
            strategy_html = render_to_string("composer/strategy.html", context)
            print(strategy_html)
            strategiesList.objects.create(script=strategy_html)
            return render(request, "composer/index.html", context)
    else:
        return render(request, "composer/index.html")

You forgot to show US the output.

1 Like

The issue was caused by fields being reset when the first button (Generate) was clicked.
As a result, if the second button (Save) was triggered, the values would be set to “None” and not displayed when the context was saved in the model.

Thank you for your help.

Here is the output saved in the model which now contains the context variables:

<!-------------------------------------- Right-side EasyLanguage & DTL output -------------------------------------->

<div class="right" id="output" style="font-size: 11px;">
    // EasyLanguage code composer by ©SOACM. All rights reserved // <br>
    <br>

    <!-------------------------------------- Breakout -------------------------------------->
    
        input: StartTime(123123), EndTime(123123), MyStopLoss(0), MyTakeProfit(0); <br>
        var: bool MyTime(False), int MP(0); <br>
            MP = MarketPosition; <br>
            MyTime = False; <br>
            if Time >= StartTime and Time <= EndTime and EntriesToday(date[0]) < 1 then MyTime = True; <br>
            <br>
            
            
            // Levels <br>
            if date <> date[1] then begin <br>
            var: highd1(0), lowd1(0); <br>
            highd1 = HighS(1); <br>
            lowd1 = LowS(1); <br>
            end; <br>
            
            <br>
            
            // Entries <br>
                <!------------ Patterns ------------>
                <!------------ Up close ------------>
                
                <!------------ Patterns End ------------>
                
            
                if MP = 0 and <br>
                
                MyTime = True and <br> 
                Close < highd1 then <br>
                begin <br>
                buy("Long") next bar at highd1 stop; <br>
                end; <br>
                if Time >= 1500 then sell next bar at open; <br>
                <br>
                if MP = 0 and <br>
                
                MyTime = True and <br> 
                Close > lowd1 then <br>
                begin <br>
                sellshort("Short") next bar at lowd1 stop; <br>
                end; <br>
                if Time >= 1500 then buytocover next bar at open; <br>
                <br>

            
            
        <br>
        // Exit <br>
        Setstopcontract; <br>
        if MyStopLoss > 0 then Setstoploss(MyStopLoss); <br>
        if MyTakeProfit > 0 then Setprofittarget(MyTakeProfit); <br>
        <br>

    
    <!-------------------------------------- Breakout end ----------------------------------->


    <!-------------------------------------- Reversal --------------------------------------->
    
    <!-------------------------------------- Reversal end ------------------------------------->
</div>