Django for loop работает на одной странице шаблона, но исчезает в других местах?
Я написал цикл Django for, который итерирует каждый экземпляр моей модели Supplier для отображения каждого экземпляра в навигационной панели. Однако по какой-то причине он выводится только на одном из моих шаблонов, а не на главной странице. Вот цикл, о котором идет речь:
<ul class="nav-drop">
{% for supplier in suppliers %}
<li>
<a href="{% url 'supplier' pk=supplier.pk %}">{{ supplier.name }}</a>
</li>
{% endfor %}
</ul>
вот мой файл views.py:
from django.shortcuts import render
from . models import Supplier
# Create your views here.
def suppliers(request):
suppliers = Supplier.objects.all()
context = {'suppliers': suppliers}
return render(request, 'suppliers/suppliers.html', context)
def supplier(request, pk):
supplier = Supplier.objects.get(id=pk)
context = {'supplier': supplier}
return render(request, 'suppliers/supplier.html', context)
from django.urls import path
from . import views
urlpatterns = [
path('suppliers/', views.suppliers, name='suppliers'),
path('supplier/<str:pk>/', views.supplier, name='supplier')
]
и рассматриваемая модель:
class Supplier(models.Model):
name = models.CharField(max_length=200, blank=True, null=True)
logo_image = models.ImageField(null=True, blank=True, upload_to='models/',
default="models/default.jpg")
marketing_image = models.ImageField(null=True, blank=True, upload_to='models/',
default="models/default.jpg")
description = models.TextField(blank=True, null=True)
short_description = models.TextField(max_length=200, blank=True, null=True)
social_facebook = models.CharField(max_length=200, blank=True, null=True)
social_twitter = models.CharField(max_length=200, blank=True, null=True)
social_instagram = models.CharField(max_length=200, blank=True, null=True)
social_youtube = models.CharField(max_length=200, blank=True, null=True)
social_linkedin = models.CharField(max_length=200, blank=True, null=True)
social_website = models.CharField(max_length=200, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
id = models.UUIDField(default=uuid.uuid4, unique=True,
primary_key=True, editable=False)
Я пытался часами, но, к сожалению, не смог найти решение
Похоже, что вы передаете список поставщиков только в одном из ваших представлений. Поэтому в одном из них есть что отображать, а в другом нет, основным решением будет добавление поставщиков в контекст всех ваших представлений.
# Create your views here.
def suppliers(request):
suppliers = Supplier.objects.all()
context = {'suppliers': suppliers}
return render(request, 'suppliers/suppliers.html', context)
def supplier(request, pk):
suppliers = Supplier.objects.all()
supplier = Supplier.objects.get(id=pk)
context = {'supplier': supplier, 'suppliers': suppliers}
return render(request, 'suppliers/supplier.html', context)
Как вы можете видеть, это противоречит принципу DRY, делая ваш код грязным. Одним из возможных решений является представление для отправки AJAX из вашего base.html (где вы, вероятно, включили навигационную панель):
base.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<header>
{% include 'includes/navbar.html' %}
</header>
<body>
{% block content%}
{% endblock content%}
</body>
<footer>
<script>
fetch("{% url 'core:supplier_list_ajax' %}")
.then((response) => response.json())
.then((data) => {
let e = document.getElementById("second-choice");
for (let key in data['suppliers']){
id = data['suppliers'][key].id
name = data['suppliers'][key].name
url = `/supplier/${id}/`
e.innerHTML += `<a href="${url}">${name}</a><br>`
}
});
</script>
</footer>
</html>
navbar.html
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
Normal Dropdown
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
{% for supplier in suppliers %}
<li>
<a href="{% url 'core:supplier' pk=supplier.pk %}">{{ supplier.name }}</a>
</li>
{% endfor %}
</ul>
<button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
AJAX Dropdown
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
<li id="second-choice">
</li>
</ul>
</div>
views.py
from django.shortcuts import render
from django.http import JsonResponse
from .models import Supplier
def suppliers(request):
suppliers = Supplier.objects.all()
context = {'suppliers': suppliers}
return render(request, 'suppliers/suppliers.html', context)
def supplier(request, pk):
supplier = Supplier.objects.get(id=pk)
context = {'supplier': supplier}
return render(request, 'suppliers/supplier.html', context)
def supplier_list_ajax(request):
suppliers = list(Supplier.objects.all().values('name','id'))
return JsonResponse({'suppliers': suppliers})
urls.py
from django.urls import path
from core import views
app_name = 'core'
urlpatterns = [
path('suppliers/', views.suppliers, name='suppliers'),
path('supplier/<str:pk>/', views.supplier, name='supplier'),
path('supplier/list/ajax/', views.supplier_list_ajax, name='supplier_list_ajax')
]
Я оставил оба выпадающих списка, чтобы вы могли увидеть разницу в действии.