I am trying to figure out a way to print values from two different context variables in a single loop. I have tried the zip() method but it does not seem to work and does not print variables on the template.
This is how I tried
index.html
<tbody>
{% for item1, item2 in mylist %}
<tr>
<td><a href="/{{ url.short_url }}">/{{ item1.short_url }}</a></td>
<td>{{ item1.original_url }}</td>
<td>{{ item1.created_at }}</td>
<td>{{ item1.clicks|intcomma }}</td>
<td>{{ item2.browser }}</td>
<td>{{ item2.platform }}</td>
<td><a href="#">
<svg viewBox="0 0 16 16" version="1.1" width="16" height="16"
aria-hidden="true">
<path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z">
</path>
</svg>
</a></td>
</tr>
{% endfor %}
</tbody>
views.py
def index(request):
urls = Url.objects.order_by('-created_at')
clicks = Click.objects.order_by('-created_at')
# context = {'urls': urls, 'clicks': clicks}
mylist = zip(urls, clicks)
context = {
'mylist': mylist,
}
return render(request, 'heyurl/index.html', context)
But on running the local server I don't see anything on the table view.
What am I doing wrong here? Are there any alternatives ?
Here's my current version of code.
models.py
from django.db import models
class Url(models.Model):
short_url = models.CharField(max_length=255)
original_url = models.CharField(max_length=255)
clicks = models.IntegerField(default=0)
created_at = models.DateTimeField('date created', auto_now_add=True)
updated_at = models.DateTimeField('date updated', auto_now=True)
class Click(models.Model):
url = models.ForeignKey(Url, on_delete=models.CASCADE, related_name='related_clicks')
browser = models.CharField(max_length=255)
platform = models.CharField(max_length=255)
created_at = models.DateTimeField('date created', auto_now_add=True)
updated_at = models.DateTimeField('date updated', auto_now=True)
index.py
def index(request):
urls = Url.objects.order_by('-created_at')
clicks = Click.objects.order_by('-created_at')
context = {'urls': urls, 'clicks': clicks}
return render(request, 'heyurl/index.html', context)
templates/index.html
<tbody>
{% for url in urls %}
<tr>
<td><a href="/{{ url.short_url }}">/{{ url.short_url }}</a></td>
<td>{{ url.original_url }}</td>
<td>{{ url.created_at }}</td>
<td>{{ url.clicks|intcomma }}</td>
<td>{{ click.browser }}</td>
<td>{{ click.platform }}</td>
<td><a href="#">
<svg viewBox="0 0 16 16" version="1.1" width="16" height="16"
aria-hidden="true">
<path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z">
</path>
</svg>
</a></td>
</tr>
{% endfor %}
</tbody>
CodePudding user response:
In views.py :
try using map instead of zip especially if the two lists don't have the same length
mylist = map(None, urls, clicks)
in views.py
def index(request):
urls = Url.objects.order_by('-created_at')
clicks = Click.objects.order_by('-created_at')
mylist = zip(urls, clicks) # this should be fine but if it doesn't work try mylist= map(None, urls, clicks)
context = {
'mylist': mylist,
}
return render(request, 'heyurl/index.html', context)
in template/index.html
<tbody>
{% for url, click in mylist %}
<tr>
<td><a href="/{{ url.short_url }}">/{{ url.short_url }}</a></td>
<td>{{ url.original_url }}</td>
<td>{{ url.created_at }}</td>
<td>{{ url.clicks|intcomma }}</td>
<td>{{ click.browser }}</td>
<td>{{ click.platform }}</td>
<td><a href="#">
<svg viewBox="0 0 16 16" version="1.1" width="16" height="16"
aria-hidden="true">
<path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z">
</path>
</svg>
</a></td>
</tr>
{% endfor %}
</tbody>
CodePudding user response:
This is an alternative
Just loop through the Click
Objects and reach their Url
pair through the ForeignKey, It would be a lot easier!
def index(request):
clicks = Click.objects.all().order_by('-created_at')
context = {'clicks': clicks}
return render(request, 'heyurl/index.html', context)
<tbody>
{% for i in clicks %}
<tr>
<td><a href="/{{ i.url.short_url }}">/{{ i.url.short_url }}</a></td>
<td>{{ i.url.original_url }}</td>
<td>{{ i.url.created_at }}</td>
<td>{{ i.url.clicks|intcomma }}</td>
<td>{{ i.browser }}</td>
<td>{{ i.platform }}</td>
<td><a href="#">
<svg viewBox="0 0 16 16" version="1.1" width="16" height="16"
aria-hidden="true">
<path fill-rule="evenodd" d="M16 14v1H0V0h1v14h15zM5 13H3V8h2v5zm4 0H7V3h2v10zm4 0h-2V6h2v7z">
</path>
</svg>
</a></td>
</tr>
{% endfor %}
</tbody>
I say this because the current way you are doing it there is a possibility of one of them is missing and then it gets all sorts of screwed up
# This is just illustrating the point
# Pairs
Click0 - > Url0,
Click1 - > None,
Click2 - > Url2,
Click3 - > Url3,
## Loop Output
Click0 - > Url0,
Click1 - > Url2, # x :(
Click2 - > Url3, # x :(
Click3 - > None, # Actually Click3 might not even show!