In many cases when developing a Django application, you will be querying a database and displaying the results on a webpage (otherwise, why would you be using Django?). I'm going to go over a quick and easy way to display a certain amount of those results in sets within a Django template (2-to-a-row, 3-to-a-row, etc).
When you send the topcars variable to the Django template, it should contain 30 results.
However, the problem with this setup is that you'll have a new table row for each result. You probably don't want that. You could enclose the for loop within the table row, but then you'll only have one table row. So what do we know? We know that we'll have at least one table row, and we know that we want to create a new row for every n results, within reason. So let's say for this example that we only want 5 results per row:
Tweet
The Model
Let's assume I have the following model for this example:
class TopCar(models.Model):
make = models.CharField(max_length=100)
model = models.CharField(max_length=100)
year = models.IntegerField()
Using this model, I've stored my 30 favorite cars for each year in the database. I want the user to be able to select any particular year and display all of the cars stored for that year. Simple, right?
However, each result displayed will include the make and model and some basic stats about the car (HP, 0-60 time, 1/4-mile time). As you can imagine, each result will take up a decent amount of space, so it wouldn't make sense to lump all 30 cars into a single row or list.
However, each result displayed will include the make and model and some basic stats about the car (HP, 0-60 time, 1/4-mile time). As you can imagine, each result will take up a decent amount of space, so it wouldn't make sense to lump all 30 cars into a single row or list.
The Query
So you want to grab all the objects for any particular year. You will probably have a query that looks something like this:
topcars = TopCar.objects.get(year=request.GET['year'])
When you send the topcars variable to the Django template, it should contain 30 results.
The Template
Moving over to the Django template, you'll probably use a for loop to iterate through the results in topcars:
<table>
{% for car in topcars %}
<tr>
<td>
{{ car.make }} {{ car.model }}
<br>
{{ car.hp }} - {{ car.zeroto60 }} - {{ car.quartermile }}
</td>
</tr>
{% endfor %}
</table>
However, the problem with this setup is that you'll have a new table row for each result. You probably don't want that. You could enclose the for loop within the table row, but then you'll only have one table row. So what do we know? We know that we'll have at least one table row, and we know that we want to create a new row for every n results, within reason. So let's say for this example that we only want 5 results per row:
<table>
<tr>
{% for car in topcars %}
<td>
{{ car.make }} {{ car.model }}
<br>
{{ car.hp }} - {{ car.zeroto60 }} - {{ car.quartermile }}
</td>
{% if forloop.counter|divisibleby:"5" %}
</tr>
<tr>
{% endif %}
{% endfor %}
</table>
Ok, now we're getting somewhere! So the first <tr> tag is outside of the for loop (our assumption that there will always be at least one table row), and an ending </tr> tag is created along with a new <tr> tag (to start a new row of results) every 5 results. We did this by using Django's divisibleby filter. This filter allows you to check if the preceding variable (in our case, the for loop counter) is divisible by the specified number (for this example, 5). This is exactly what we want, because by the time the fifth result in the for loop is processed, the forloop.counter variable will be 5, which is of course divisible by 5. Makes sense, right?
The End Result
But there's one last problem here. If the loop ends, we have nothing here to close the last <tr> tag, so we'll have an open table row when the loop has ended. Additionally, if the last result happens to be divisible by 5, we'll have opened a new row and there will be nothing to go in it. We'll just have an empty row, and that's also not good. Let's fix that:
<table>
<tr>
{% for car in topcars %}
<td>
{{ car.make }} {{ car.model }}
<br>
{{ car.hp }} - {{ car.zeroto60 }} - {{ car.quartermile }}
</td>
{% if forloop.last %}
</tr>
{% else %}
{% if forloop.counter|divisibleby:"5" %}
</tr>
<tr>
{% endif %}
{% endif %}
{% endfor %}
</table>
What I've done here is add a new check to see if we're currently iterating through the final result in the for loop, using the forloop.last variable. So now our code basically reads like this: For every car in the topcars list, create a new table cell and fill it with some values; if we're on the final result in the topcars list, close the table row; otherwise, on every 5th result, close the table row and start a new one.
Success!
Success!
Tweet
0 comments:
Post a Comment