Is it possible to get a list of strings to use join statement on

I am trying to dynamically populate some paragraph tags with information from my database. I would like each paragraph tag to be in a format like the following <p>Insurances: BCBS, Aetna, Molina</p> where the BCBS, Aetna, Molina are insurances associated with a given therapist in my database.

In my models, I have Therapist and Insurance classes that are defined by a many-to-many relationship as follows:

class Therapist(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    license_type = models.CharField(max_length=50)
    active = models.BooleanField(default=True)
    certifications = models.ManyToManyField(Certification)
    insurances = models.ManyToManyField(Insurance)
    populations = models.ManyToManyField(Population)
    bio = models.TextField()
    picture = models.ImageField(upload_to="static/bio_pics", default=None)

    def __str__(self) -> str:
        return f"{self.first_name} {self.last_name}, {self.license_type}"

class Insurance(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self) -> str:
        return self.name

My template code so far is below, with the relevant section being the <p class="insurances> part of the code:

            {% for therapist in therapists %}
                <div class="therapist">
                    <img class="bio-pic"
                         alt="{{ therapist.first_name }} {{ therapist.last_name }} smiling at the camera."
                         src="{{ therapist.picture }}" />
                    <h3 class="therapist-name">{{ therapist.first_name }} {{ therapist.last_name }}, {{ therapist.license_type }}</h3>
                    <p class="insurances">
                        Insurance:
                        {% for insurance in therapist.insurances.all %}<strong>{{ insurance.name }}</strong> |{% endfor %}
                    </p>
                    <a class="therapist-link" href="/{{ therapist.id }}">Learn more about {{ therapist.first_name }}</a>
                </div>
            {% endfor %}

What I would like to be able to do is get a list of strings with all of the insurances for each therapist so that I could do something like {{ therapist.insurances.all|join: ", " }} but that code obviously fails.

Is there a way to get a list of strings with names of every insurance a therapist has or do I need to take a different approach to accessing that information?

Welcome @r-ofarrell !

If you don’t want to render the names individually, then the easiest answer I can think of would be to create a model method that builds the list, then render the method in the template.

Depending upon what all you may want to do with this data, you could either return the list in the method and render it in the template using the join as you show here, or the method could return the string to be rendered directly.
(Your choice is likely to depend upon whether you will ever need this list elsewhere in your project. If not, then you’re better off returning the preformatted list.)

Hi Ken. Thank you so much for the reply.

When you say create a model method, would that be something like the following on the Therapist class:

def to_list_of_strings(self):
        return list(map(lambda insurance: insurance.name, self.insurances))

It also looks like I would need to define an __iter__ method as well. Am I on the right track with that?

I apologize if I am missing something obvious, but my Python knowledge is… developing to say the least.

That’s the basic idea, but using the ORM makes it a lot easier than that.

If you want to return the list, it could be something like this:

def to_list_of_strings(self):
    return list(self.insurances.all().values_list('name', flat=True))

Or, you could do the join in the method, which would be more performant than doing it in the template:

def to_string_from_list(self):
    return ", ".join(self.insurances.all().values_list('name', flat=True))

Ken, I cannot thank you enough for your help. I’ve been banging my head against that problem for awhile. Your help is deeply appreciated.