Home > OS >  Using " ,".join in Django splitting every character, rather than item in list
Using " ,".join in Django splitting every character, rather than item in list

Time:02-17

I have a list of book genres I'm trying to display in in template using this code

{% if title.my_books.genre.all %}
     <li >
     <kbd>Genres</kbd>
     {% for genre in title.my_books.genre.all %}
         {{genre.genre}}{% if not forloop.last %}, {% endif %}
      {% endfor %}</li> 
{% endif %}

My goal is to display the items like so Autobiography, Biography, Memoir. And the above code DOES THAT. However, I've been asked to alter the code to use Django's join template tag detailed here https://docs.djangoproject.com/en/3.2/ref/templates/builtins/#join

Let's the say the items of the list are ['Autobiography', 'Biography', 'Memoir']

Obviously, if I don't have this line {% if not forloop.last %}, {% endif %} and just have {{genre.genre}} in the for loop,

the values will display like Autobiography Biography Memoir

However if I alter the above code like so following Django's docs:

{% if title.my_books.genre.all %}
     <li >
     <kbd>Genres</kbd>
     {% for genre in title.my_books.genre.all %}
         {{ genre.genre|join:" ," }}
      {% endfor %}</li> 
{% endif %}

The output on the template looks like this:

A ,u ,t ,o ,b ,i ,o ,g ,r ,a ,p ,h ,y B ,i ,o ,g ,r ,a ,p ,h ,y M ,e ,m ,o ,i ,r

How can I properly display the values like so: Autobiography, Biography, Memoir using Django's join template tag? Thanks!

CodePudding user response:

In the way you did it treats every genre.genre as a source for join, so it basically spreads every genre separatedly. Remebmer, that in Python strings can be interpreted as list of characters. So if you want to do it properly, you should pass the genres as a list of all genres in context.

views:

context['genres'] = Title.my_books.genre.all()

or even better add a method to your Model:

YourModel(models.Model):
    ...
    def get_all_genres(self):
        return self.genres.all()

and then in template:

{{ yourmodel.get_all_genres|join:', ' }}

It might now be precise, because I don't know your exact models/views, but I hope you understand that solutions.

CodePudding user response:

I see two options:

First: Generate a list in model and join it in template

In your model

class YourModel(model.Model):
    
    @property
    def genres_list(self):
        return list(self.genres.all())

In your template

Genres: {{ genre.genres_list|join:" ," }}

Second: Generates a str directly in python and show it in template

In your model

class YourModel(model.Model):
    
    @property
    def genres(self):
        return ", ".join(list(self.genres.all()))

In your template

Genres: {{ genre.genres }}

I prefer the second because if you want to show the same string on different places only need to include the property

  • Related