HTML widget display templates

Dear Community,
I would like to display a full html content as response of POST request of an API made in the views.py.

The response is a full HTML document like

b'<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>leaflet</title> <script>(function() { // If window.HTMLWidgets is already defined, then use it; otherwise create a // new object. This allows preceding code to set options that affect the //

This is my views.py

from django.shortcuts import render
from django.contrib.gis.geos import GEOSGeometry
import json
import requests

# Create your views here.

from field.models import Field


def satelliteview(request):
    if request.method=="POST":
        pass
    else:
        user_fields=Field.objects.filter(User_id=request.user.id)
        print(user_fields)
        user_fields=user_fields.first()
        print(user_fields)
        geojson=user_fields.Field

        geojson_feature = json.loads(GEOSGeometry(geojson, srid=4326).json)

        print(geojson_feature)

        API_endpoint="http://127.0.0.1:3000/AFS/htmlwidget?"
        
        auth_data = {
            "username": "XXXXXXXXXXXXXXXX",
            "password": "XXXXXXXXXXXXXXXX"
        }

        response = requests.post(API_endpoint, 
                                 json=geojson_feature, 
                                 auth=(auth_data["username"], 
                                 auth_data["password"]))
                
        print(response)
        print(response.content)
        
        context={
            "response": response.content
        }

        return render(request, 'satellite/satellite.html', context=context)

This is my template

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load leaflet_tags %}

{% block content %}
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% leaflet_js plugins="forms, geocoder, measurement" %}
    {% leaflet_css plugins="forms, geocoder, measurement" %}
    <title>New Field</title>
  </head>
  <body>
    <p>ciao</p>

    <iframe id="iframe" frameborder="0"></iframe>
    
    <script>
        document.getElementById('iframe').srcdoc = "{{response|safe}}";
    </script>
  </body>
</html>
{% endblock %}

This is my urls.py

from django.urls import path

from .views import satelliteview

urlpatterns = [
    path("satellite/", satelliteview, name="satellite"),
]

and this is the result

How can i display the html widget proprely?

My guess is that you’re passing the data as bytes, since this is the type of the .content member on the Response class. You probably are trying to access the .text member instead.

[I don’t know if this is the optimal solution, or if you should by doing it this way… but it may work]
Cheers

Thanks to reply @leandrodesouzadev,

I have changed the .content to .text of the views.py but still i have got problem to render the html as you see below

This is the views.py changed with your suggestion

from django.shortcuts import render
from django.contrib.gis.geos import GEOSGeometry
import json
import requests

# Create your views here.

from field.models import Field


def satelliteview(request):
    if request.method=="POST":
        pass
    else:
        user_fields=Field.objects.filter(User_id=request.user.id)
        print(user_fields)
        user_fields=user_fields.first()
        print(user_fields)
        geojson=user_fields.Field

        geojson_feature = json.loads(GEOSGeometry(geojson, srid=4326).json)

        print(geojson_feature)

        API_endpoint="http://127.0.0.1:3000/AFS/htmlwidget?"
        
        auth_data = {
            "username": "XXXXXXXXXXXXXXXX",
            "password": "XXXXXXXXXXXXXXXX"
        }

        response = requests.post(API_endpoint, 
                                 json=geojson_feature, 
                                 auth=(auth_data["username"], 
                                 auth_data["password"]))
                
        print(response)
        print(response.text)
        
        context={
            "response": response.text
        }

        return render(request, 'satellite/satellite.html', context=context)

I have tried to use your suggestion response.text in the template but in this way

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load leaflet_tags %}

{% block content %}
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% leaflet_js plugins="forms, geocoder, measurement" %}
    {% leaflet_css plugins="forms, geocoder, measurement" %}
    <title>New Field</title>
  </head>
  <body>
    <p>ciao</p>
    <div>
      {{response|safe}}
    </div>
    <p>ciao</p>

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

This is the results

and now render but cover the entire page and both p tag disappear. How can i isolate the html content and display both p tags?

That’s happening because you’re putting the entire html from the response into your HTML.
If you’re following a tutorial, you better double check what’s different from what you’re doing.

Actually i am not following a tutorial.

I am trying to figure out how to insert a HTML document produced by a post request inside a HTML tag element in order to costumize the position and size.

Then you need that iframe.
I wonder if there’s any other JS or CSS required (in that iframe) in order to render the map correctly.

Thanks to reply.

The html widget have all the required imports to be rendered.

Now i have changed my code to this but still get problem. :thinking:

views.py

from django.shortcuts import render
from django.contrib.gis.geos import GEOSGeometry
import json
import requests

# Create your views here.

from field.models import Field


def satelliteview(request):
    if request.method=="POST":
        pass
    else:
        user_fields=Field.objects.filter(User_id=request.user.id)
        
        user_fields=user_fields.first()

        geojson=user_fields.Field

        geojson_feature = json.loads(GEOSGeometry(geojson, srid=4326).json)

        API_endpoint="http://127.0.0.1:3000/AFS/Widget"
        
        auth_data = {
            "username": "XXXXXXX",
            "password": "XXXXXXX"
        }

        response = requests.post(API_endpoint, 
                                 json=geojson_feature, 
                                 auth=(auth_data["username"], 
                                 auth_data["password"]))
        
        response=response.text
                
        print(response)
        
        context={
            "response": response
        }

        return render(request, 'satellite/satellite.html', context=context)

This is the template

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% load leaflet_tags %}

{% block content %}
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>New Field</title>
    {% leaflet_js %}
    {% leaflet_css %}
  </head>
  <body>
    
    <p>ciao</p>
  
    <iframe srcdoc="{{ response|safe }}"></iframe>
        
    <script>
        document.getElementById('iframe').srcdoc = "{{response|safe}}";
    </script>
    
    <p>ciao</p>

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

This is my result

Screenshot 2023-09-11 192045

I have opened the console of my browser and i have got the following issues:

dataTables.bootstrap5.min.js:11 Uncaught ReferenceError: jQuery is not defined
    at dataTables.bootstrap5.min.js:11:283
    at dataTables.bootstrap5.min.js:11:308
(anonymous) @ dataTables.bootstrap5.min.js:11
(anonymous) @ dataTables.bootstrap5.min.js:11
VM452:2 Uncaught SyntaxError: Invalid or unexpected token (at VM452:2:52)
VM459:615 Uncaught TypeError: Cannot read properties of undefined (reading 'widget')
    at 13../cluster-layer-store (VM459:615:26)
    at o (VM459:1:265)
    at r (VM459:1:431)
    at VM459:1:460

When i use the following template code

{% autoescape off %}
  {{ response }}
{% endautoescape %}

the html document render but again cover the entire page.

See the results