tl;dr Use a custom Django template filter.

By default Django comes with many built-in template tags and filters that perform standard conversions. There’s even one for phone numbers, phone2numeric, that will convert 800-COLLECT into 800-2655328. But to get the pretty formatting we want we need to create our own custom Django template filter.

If your phone number is stored as a charField string in your database, proceed directly to the code below.

If it’s stored as an Integer or Decimal use Django’s built-in stringfilter, which will convert an object into its string value before being passed to your function.

Here is the custom template filter code you need:

# template_filters.py
from django import template
register = template.Library()

@register.filter(name='phone_number')
def phone_number(number):
"""Convert a 10 character string into (xxx) xxx-xxxx."""
first = number[0:3]
second = number[3:6]
third = number[6:10]
return '(' + first + ')' + ' ' + second + '-' + third

Then in your template:

# index.html
{% load template_filters %}

{% for number in object_list %}
	<a href="tel:+{{number.phone_number}}">{{number.phone_number|phone_number}}</a>
{% endfor %}

This example assumes you are looping through a database field called “phone_number.”