Django: a custom template tag to convert links inside of a TextField and change the hyperlink text

The scenario is that there are some dynamic texts on some templates, that will contain hyperlinks. For this, I have a SiteDataKeyValue model, in which the dynamic texts for different parts of the template are inputted. This is the model:

class SiteDataKeyValue(models.Model):
    key = models.CharField(
        max_length=200, verbose_name="نام متن مورد نظر", unique=True
    )
    value = models.TextField(verbose_name="متن")

    def __str__(self):
        return self.key

A solution that I've found already, is Django urlize template tag. As mentioned in the docs, this tag converts texts like https://www.google.com to <a href="http://www.google.com" rel="nofollow">www.google.com</a>, which is nice but not what I'd like to achieve. I want to be able to change the hyperlink text, so the output would be something like: <a href="http://www.google.com" rel="nofollow">Click Here!</a>.

I searched for a bit, came across modules like bleach, which is a fine module, but I couldn't find the answer I was looking for (I skimmed through the docs and there was nothing about the hyperlink text).

Also I saw a comment somewhere telling that this could be achieved by writing a custom Django template tag, but although I tried to do this regarding the custom template filters docs, I didn't have a clue to how to achieve this.

I'm not asking for the code, although it would be really appreciated if you provide instructions for writing this custom template tag, or better, if you could point me to something like this that is already out there.

First of all you can extend urlize tag like the answer in this

or you can change the main code which you can find it in django.utils.html and override its url variable to change it.

But I think the best method is extending the urlize tag like this:

{% text | urlize | change_a_text_filter:{{ dome_new_a_text }} %}

then you can scrape the text and use regex to find >sample-text</a> then you can change it to the argument that defines in your tag

from django import template

register = template.Library()

@register.simple_tag
def change_a_text_filter(format_string, arg):
    # find the url that made in urlize with regex
    # change it with arg
    # return the result

I was on a completely wrong road to solve this problem. I was trying to urlize a link from TextField, but didn't consider the fact that I only needed to implement html code as <a href="https://www.link.com">Visit link.com!</a> in the TextField, and then use safe template tag to render html directly as below:

{{ text.value|safe }}

So in this solution, there is no need to urlize, and of course there is no need to extend this tag neither.

Back to Top