Embedded link displays when hardcoded but not when passed as variable

I have the following problem in my django project when trying to display an embedded google maps link in my page. This works (renders the Google Maps iframe with a populated map) when I hardcode the src URL but not when I pass it in my context even though they result to the same text string.

This is my html detailview.html:

        {% if maps_link is not None %}
          <iframe
            src="https://maps.google.com/maps?q=-28.4457436,21.268374&hl=en&z=14&amp;output=embed"            
            loading="lazy"
            referrerpolicy="no-referrer-when-downgrade"
          ></iframe>
        {% endif %}

The src URL as it is shown above displays as I want it to, but when I do the following:

        {% if maps_link is not None %}
          <iframe
            src="{{ maps_link }}"    <!-- This gets blocked -->   
            loading="lazy"
            referrerpolicy="no-referrer-when-downgrade"
          ></iframe>
        {% endif %}

then my browser gives me the following warning:

To protect your security, www.google.com will not allow Firefox to display the page if another site has embedded it. To see this page, you need to open it in a new window.

This is my views.py where the context is generated. I tried to get around it by applying xframes exemptions but that made no difference:

from django.views.decorators.clickjacking import xframe_options_exempt
from django.http import Http404, HttpResponse

@xframe_options_exempt
def detail(request, database_reference):
    try:
        obj = Consolidated.objects.get(database_reference=database_reference)
    except Consolidated.DoesNotExist:
        raise Http404("This database object does not exist: " + database_reference)

    context = {
        "content" : content_list,
        "maps_link": obj.location_link
    }

    print(context['maps_link'])
    print(type(context['maps_link']))

    template = loader.get_template("home/detailview.html")
    return HttpResponse(template.render(context, request))

print(context['maps_link']) results to https://maps.google.com/maps?q=-25.797944,28.307176&hl=en&z=14&amp;output=embed

and

print(type(context['maps_link'])) results in the following type <class 'str'>

So printing out the {{ maps_link }} value results to the exact same string as the hardcoded URL. Can someone tell me why this is happening (what's the difference between a string hardcoded in the html side and a string passed as a parameter) and more importantly how I can get around it? Thanks

In HTML, &amp; is automatically converted to the character &. Therefore, the URL

https://maps.google.com/maps?q=-28.4457436,21.268374&hl=en&z=14&amp;output=embed

is actually

https://maps.google.com/maps?q=-28.4457436,21.268374&hl=en&z=14&output=embed.

However, when Django does the substitution, it does NOT replace the special sequence &amp;. Therefore, the URL visited is a different one.

To resolve the issue, you can do the replacement yourself. Replace

context = {
    "content" : content_list,
    "maps_link": obj.location_link
}

with

context = {
    "content" : content_list,
    "maps_link": obj.location_link.replace('&amp;', '&')
}

and this should solve the issue.

Back to Top