I hate myself for being that StackOverflow user who "answers" a question by saying "don't do it that way, do it this way" but ... don't do it that way, do it this way:
Django really encourages you to do this sort of logic in the view. You "should" be padding your placement_list
to the correct length before sending it to your template for rendering.
You said that placement_list
is currently a queryset defined in the view and then sent as-is to the template. Let's say that the way you're currently doing that looks vaguely like this:
placement_list = MyModel.objects.all()
What if we want this to always be at least 50 items long? We can convert placement_list
from a queryset to a list and add dummy MyModel
objects to that array.
padded_placements = placement_list + [MyModel()]*(50-len(placement_list))
Note that we're instantiating MyModel()
objects here, but not actually doing a Django-style create
and/or saving anything to the database. These are empty "dummy" objects that we can send to our template to use as placeholders without polluting our real data.
Let's make one tweak to the line we just wrote, to make templating easier:
padded_placements = placement_list + [MyModel(url='DEFAULT')]*(50-len(placement_list))
Now all of our dummy objects will have their url
attribute set to the string DEFAULT
. This wouldn't pass object-level URL validation, but that doesn't matter since we're not saving these dummies to the DB - those validators never get called.
Send padded_placements
to the template and look for our custom attribute:
{% for placement in padded_placements %}
{% if placement.url != 'DEFAULT' %}
<a href="{{ placement.url }}">
<img src="{{ MEDIA_URL }}{{ placement.image }}"/>
</a>
{% else %}
<p>do default stuff</p>
{% endif %}
{% endfor %}
Two notes:
Your dummy MyModel
objects may need additional attributes set, depending on how those objects get used in the template and how your model represents itself. For example, if your str/repr method relies on MyModel.description
then you'll need to include that field.
Passing a list to your template instead of a queryset means that you lose access to queryset stuff within your template. That is a great thing, since any queryset-type logic (filtering, exists
checks, etc) you're doing really, REALLY should be done in the view as opposed to the template.