Как вывести несколько значений из двух списков в шаблоне django
Я пытаюсь найти способ вывести значения из двух различных контекстных переменных в одном цикле. Я пробовал метод zip() , но он, похоже, не работает и не выводит переменные на шаблон.
Вот как я пытался
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 class="octicon octicon-graph" 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)
Но при запуске локального сервера я ничего не вижу в представлении таблицы.
Что я делаю не так? Есть ли какие-нибудь альтернативы?
Вот моя текущая версия кода.
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 class="octicon octicon-graph" 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 :
попробуйте использовать map вместо zip, особенно если два списка имеют разную длину
mylist = map(None, urls, clicks)
в 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)
в 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 class="octicon octicon-graph" 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>
Это альтернатива
Просто пройдитесь циклом по объектам Click
и дойдите до их пары Url
через ForeignKey, Это будет намного проще!
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 class="octicon octicon-graph" 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>
Я говорю это, потому что при текущем способе, которым вы это делаете, есть возможность того, что один из них отсутствует, и тогда все портится
# 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!