Dynamic hyperlinks in TextField redirecting / routing to correct location remotely and locally

When an Admin Dashboard user enters content into a TextField model object which includes an inline HTML element that reads: <a href="{% url 'about' %}">...more about this website can be found here</a>, I’m trying to get it to do two things:

  1. Redirect to localhost:8000/about when testing the site in my development environment and
  2. Redirect to https://ProductionDomainName.com/about/ remotely on my web server.

The problem is, after entering <a href="{% url 'about' %}">...more about this website can be found here</a> in a TextField with the other text content, when clicking the link, it throws a 404 Page Not Found and my address bar looks like this: http://localhost:8000/%7B%%20url%20'about'%20%%7D.

The only way to get <a href="{% url 'about' %}">...more about this website can be found here</a> to parse properly and route to localhost:8000/about locally and https://ProductionDomainName.com/about/ remotely successfully in both environments is if I hard code the {% url 'about' %} hyperlink in the template. But that’s not what I am trying to accomplish. What I am trying to do is get the {% url 'about' %} based hyperlink to redirect to the right address when the Django Admin Dashboard user enters it into their TextField box.

Is this even possible? I suspect you people will say that this is not possible. If that’s the case, what alternatives do I have to get my Django CMS to handle dynamic hyperlinks consistently remotely but also with my client’s Postres production content mirrored to my local development environment?

How are you rendering that text field such that you are getting an actual link being rendered?

The short answer is that that field will need to be rendered as part of the template. If you’re just including the data from that field within your page as something like {{ html_field }}, you will need to use the template engine to render that field.

I will point out that providing this functionality is an extreme security risk. The individual creating this type of input has access to the complete context of the page being rendered. I can’t imagine making this available to anyone-who-isn’t-staff.

If you really want to ignore the security issues, you’ve got a couple different options available to you. You can render that field to text and supply that text to the context being used to render the main page. Or you could pull the entire template together and inject this field into your template, allowing you to call the rendering engine once. Or, you could create a custom filter that calls the rendering engine for the value currently being rendered.

If you want to maintain some sense of security, then you don’t want to allow for direct entry of template directives. Find some other kind of syntax to allow for limited and controlled access to data elements and create your own rendering engine.

1 Like

Thank you for highlighting the security risks. The users entering the text field will only be on staff. There are no entry points for common website visitors. Like, there is no comments section for web visitors to enter data.

@KenWhitesell: You explained that I have three options:

  1. You can render that field to text and supply that text to the context being used to render the main page.
  2. Or you could pull the entire template together and inject this field into your template, allowing you to call the rendering engine once.
  3. Or, you could create a custom filter that calls the rendering engine for the value currently being rendered.

What would be my next steps to implement the easiest of the above 3 options that you outlined, Ken?

For example, how might I render the field text and feed it to the context to be rendered? Where would I begin to learn more about this?

Also, how could I implement a custom filter? I am not going to ask you to do it for me, because that isn’t a fair ask. But where in the Django docs would I need to work with for writing a feature like this?

I don’t know what I would consider “easiest”. None are all that particularly difficult, each has individual pros & cons based upon a number of different factors. (One such factor being the question about how many instances of this are needed across how many views / templates / models. What’s easiest for one field in one model in one template being rendered by one view can become a maintenance headache for 10 fields in 10 models across 10 templates.)

I would start with the Components section of the Templates doc (through the rest of that page), proceeding to the Template API docs.

The key here is that you’re not looking to generate an HttpResponse from the template, so the render shortcut doesn’t help you here. You want to run the rendering engine to return a string, then add that string to your context, then render that variable in the template.

For discussion purposes only - I don’t have any solid example to show:

raw_field = MyModel.objects.get(id=some_id).field_to_be_rendered
template = Template(raw_field)
context = Context({"name":"value",...})
generated_html = template.render(context)
final_context = {'rendered_field': generated_html}
render("some-template.html", final_context)

and then, in some-template.html you have:

{{ rendered_field }}

See Custom template tags and filters | Django documentation | Django

:wink: It’s a fair ask. There’s no guarantee I’m going to provide an answer though…
:grinning_face_with_smiling_eyes:

1 Like

Thank you @KenWhitesell, you have done a terrific job providing guidance and next steps. I’ve got my work cut out for me. :slight_smile: