khashashin
khashashin

Reputation: 1137

Formatting ampersand adds unexpected characters

Using Djoser Im trying to generate right url for my frontend. I have to have ampersand in my url string and Djoser do format this url before sending it to my frontend. The url looks like:

https://localhost:4200/activate?id=MjA&token=540-cad5f834d5508ebdd78e

But the final result that I get looks like note "amp;" after &:

http://localhost:4200/activate?id=MjE&token=541-c0437e0afd6261fd4833

I tried following solutions but none of them works (\u0026, {\u0026}, {\u0026:c}, &&):

print("https://localhost:4200/activate?id={uid}\u0026token={token}".format(uid="MjA", token="540-cad5f834d5508ebdd78e"))
print("https://localhost:4200/activate?id={uid}{\u0026}token={token}".format(uid="MjA", token="540-cad5f834d5508ebdd78e")) <-- returns KeyError: '&'
print("https://localhost:4200/activate?id={uid}{\u0026:c}token={token}".format(uid="MjA", token="540-cad5f834d5508ebdd78e")) <-- returns KeyError: '&'

NOTE: I can't directly change code in format() part, this will be handled by Djoser. The part that I can pass is actually only assign the string value to activation url like there: 'ACTIVATION_URL': 'activate?id={uid}{\u0026:c}token={token}', So I have to write my solution in this string.

NOTE2: I tried it in jupiter, there all works fine, I get the right url when I do it this way:

print("https://localhost:4200/activate?id={uid}\u0026token={token}".format(uid="MjA", token="540-cad5f834d5508ebdd78e"))

enter image description here

Directly adding & returns to frontend same url with amp; behind &

UPDATE Djoser template overwriting

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        ...
    },
]

enter image description here

Upvotes: 1

Views: 1847

Answers (1)

John Szakmeister
John Szakmeister

Reputation: 47032

After some back and forth discussion, it turns out that Djoser wants to send an activation email and the contents are being generated from a Django template. The issue is that Django does HTML escaping by default, so the & character is being converted to an HTML entity, &amp;, which is not what is desired here.

The answer is to mark the url as being HTML safe by piping it through a filter. This effectively means replacing {{ url }} with {{ url|safe }}. The best way to do this is to create a new template to override the one provided by Djoser and put in the required content. This template needs to reside in the project templates area as "email/activation.html". There is some documentation in Django on how this is done too.

Once the template is working correctly, then the url should be emitted directly with no escaping.

Upvotes: 4

Related Questions