How to Use Jinja-Like Syntax in Julia Web Apps with Oxygen.jl

Oxygen.jl is a simple microframework that is quite useful for creating web apps and APIs in Julia. In my opinion, it is like the Flask of Julia as GenieFramework.jl is like the Django of Julia. Since it is quite new( Sept 2023), it does not yet have support for using Jinja – a templating engine used in most Python web frameworks like Flask, Django, etc.

In this tutorial, we will explore how to add Jinja-Like Syntax for our web apps that we build with Oxygen.jl and HTTP.jl.

There are two main libraries that we can use to offer this feature. These include

  • Mustache.jl: a templating package
  • OteraEngine.jl: templating engine

Let us see how to use Mustache.jl and OteraEngine.jl. With Mustache.jl we can pass data from our backend to our frontend using the {{ }} syntax hence the name Mustache. However to get all the support that most Jinja Templating engine offer, OteraEngine.jl can be used instead.

Below are the two solutions( I hope to create a Pull Request as Contribution to Oxygen.jl in the future)

Installing the Packages

] add OteraEngine Mustache

Using Mustache.jl in Julia Web Apps

using Oxygen
using HTTP
using Mustache


function render_html(html_file::String ,context::Dict = Dict(); status=200, headers = ["Content-Type" => "text/html; charset=utf-8"]) :: HTTP.Response
    is_context_empty = isempty(context) === true
    # Return the raw HTML content as the response body without context 
    if is_context_empty
        io = open(html_file, "r") do file
            read(file, String)
        end
        template = io |> String
    else
         # Render the Mustache template with the provided context
        io = open(html_file, "r") do file
            read(file, String) 
        end
        template = String(Mustache.render(io, context))
    end

    return HTTP.Response(status, headers, body= template)
end

We can now use it inside our Oxygen.jl App as below

# how to render html without jinja templating
@get "/home" function(req::HTTP.Request)
    return render_html("index.html",status=200)
end

# how to render html with jinja templating
@get "/blog" function(req::HTTP.Request)
    context = Dict("title" => "Crud App")
    return render_html("blog.html", context, status=200)
end

Using OteraEngine.jl in Julia Web Apps

OteraEngine.jl has both support for basic templating and also the ability to run Julia code inside html such as for loop,etc. With OteraEngine.jl you can use {{}} as well as {% %} like you would with Jinja in Python or Javascript.

using Oxygen
using HTTP
using OteraEngine


function render_template(html_file::String ,context::Dict = Dict(); status=200, headers = ["Content-Type" => "text/html; charset=utf-8"]) :: HTTP.Response
    is_context_empty = isempty(context) === true
    # Return the raw HTML content as the response body without context 
    if is_context_empty
        io = open(html_file, "r") do file
            read(file, String)
        end
        template = io |> String
    else
         # Render using OteraEngine template with the provided context
        io = open(html_file, "r") do file
            read(file, String) 
        end
        txt = io |> String
        tmp = Template(txt, path = false)
        template = tmp(tmp_init = context)
    end

    return HTTP.Response(status, headers, body= template)
end

We can now use it inside our backend and frontend html as below

@get "/blog/{title}" function(req::HTTP.Request,title::String)
    mylist = [3,5,1]
    context = Dict("title" => uppercase(title),"mylist" => mylist)
    return render_template("blog.html", context, status=200)
end

In our html file we can use both as below

<body>
    <div>
        <h2>Blog List</h2>
        <p>{{ title }}</p>
        <div>
            {% for i in mylist %}
        Hello {{i}} {{ title }}
        {% end %}
        </div>
    </div>
</body>

As you can see we can do more with OteraEngine.jl and Mustache.jl. I hope this was helpful. You can also check out the video tutorial below.

Thank you for your Attention
Jesus Saves

By Jesse E.Agbe(JCharis)

Leave a Comment

Your email address will not be published. Required fields are marked *