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-ответ

enter image description here

Вернуться на верх