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&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&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, & is automatically converted to the character &. Therefore, the URL
https://maps.google.com/maps?q=-28.4457436,21.268374&hl=en&z=14&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 &. 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('&', '&')
}
and this should solve the issue.