Django : Передача prefetch_related _set.all() в результатах Ajax-поиска
Я реализовал продукт поиска по таблице с помощью Ajax, и он хорошо работает.
Но теперь я хочу построить динамически мою таблицу с учетом того, что количество моих складов может быть увеличено.
search.js
data.forEach((item) => {
const newName = (item.nom).slice(0, 30) + "...";
tableBody.innerHTML += `
<tr>
<th><a href="{% url 'product-update' ${item.id} %}">${item.sku}</a></th>
<td>${item.etat__etat}</td>
<td class="small">${newName}</td>
<td>${item.famille__nom}</td>
<td>${item.mageid}</td>
<td>${item.adresse}</td>
models.py (модель, для которой мне нужен набор)
class SstStock(models.Model):
warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
product = models.ManyToManyField(Produit)
qty = models.IntegerField()
last_update = models.DateTimeField(default=timezone.now)
views.py
def search_product2(request):
if request.method == 'POST':
search_str = json.loads(request.body).get('searchText')
products = Produit.objects.filter(sku__icontains=search_str) | Produit.objects.filter(
nom__icontains=search_str) | Produit.objects.filter(mageid__icontains=search_str)
data = products.values(
'id',
'sku',
'nom',
[...]
'sststock',
[...]
'cau_cli',
'maxsst2',
)
return JsonResponse(list(data), safe=False)
Непосредственно в шаблоне я мог бы сделать :
шаблон
{% for produit in produits %}
{{ produit.sku}}<br>
{% for sst in produit.sststock_set.all %}
<span>{{sst.warehouse.code}} - {{ sst.qty }}</span><br>
{% endfor %}
<br>
{% endfor %}
Но я не смог найти способ передать sststock_set.all() в JsonResponse. Я получил в нем значение "sststock", но оно содержит только последнее значение набора, а не массив/дикт всего набора.
console.log()
qty: 7
sku: "ACP863"
sststock: 68095
68095 - это последний ID моего набора. Хуже того, когда я пытаюсь получить item.sststock в продукте ForEach, в моем JS он возвращает Undefined.
Есть идеи, пожалуйста?
Нашел способ применить совет @WillemVanOnsem с сериализатором.
Вообще, моя первая ошибка заключается в применении ManyToMany вместо ForeignKey на:
product = models.ManyToManyField(Produit)
После этого я установил сериализатор, который извлекает различные запасы (warehouse_id + qty) и добавляет их в модель Product (с параметром "source"):
serializers.py
from rest_framework import serializers
from .models import Produit, SstStock
class StockSearchSerializer(serializers.ModelSerializer):
class Meta:
model = SstStock
fields = '__all__'
fields = ['warehouse_id', 'qty']
class ProductSearchSerializer(serializers.ModelSerializer):
sststock = StockSearchSerializer(source='sststock_set', many=True)
class Meta:
model = Produit
fields = '__all__'
В завершение, я использую сериализатор с "many=True" в представлении и возвращаю его результат, который будет обработан JS на моей странице поиска:
views.py
def search_product(request):
if request.method == 'POST':
search_str = json.loads(request.body).get('searchText')
products = Produit.objects.prefetch_related(
Prefetch('sststock_set',
SstStock.objects.select_related('warehouse'))
).filter(sku__icontains=search_str) | Produit.objects.filter(
nom__icontains=search_str) |
Produit.objects.filter(mageid__icontains=search_str)
serializer = ProductSearchSerializer(products, many=True)
data = serializer.data
return JsonResponse(list(data), safe=False)
И, как и желалось, массив запасов добавляется в json-ответ
