Django : Получение (модели) значения __str__ foreignkey (текст) вместо его ID в результате ajax-поиска
Я использую JS для поиска товаров таким образом :
models.py (summary)
class Produit(models.Model):
famille = models.ForeignKey(Famille, on_delete=SET_NULL, null=True)
sku = models.CharField(max_length=100, unique=True)
nom = models.CharField(max_length=250)
fournisseur = models.ForeignKey(
Supplier, on_delete=models.SET_NULL, default=12, null=True)
qty = models.IntegerField()
mini = models.IntegerField()
[...]
Например, для Famille, я установил str на :
class Famille(models.Model):
nom = models.CharField(max_length=50)
[...]
def __str__(self):
return self.nom
В моем шаблоне есть поле поиска, которое прослушивается моим JS кодом
product_search.js
const searchField = document.querySelector("#searchField");
const tableBody = document.querySelector('.table-body');
const appTable = document.querySelector('.app-table');
const tableOutput = document.querySelector('.table-output');
tableOutput.style.display = 'none'
searchField.addEventListener('keyup', (e) => {
const searchValue = e.target.value;
if (searchValue.trim().length > 2) {
tableBody.innerHTML = '';
fetch("search-product2", {
body: JSON.stringify({ searchText: searchValue }),
method: "POST",
})
.then((res) => res.json())
.then((data) => {
tableOutput.style.display = 'block'
appTable.style.display = "none";
if (data.length === 0) {
tableOutput.innerHTML = '<h3>Aucun résultat.</h3>';
} else {
console.log("data", data);
data.forEach((item) => {
tableBody.innerHTML += `
<tr>
<th><a href="{% url 'product-update' ${item.id} %}">${item.sku}</a></th>
<td>${item.etat_id}</td>
<td>${item.nom}</td>
<td>${item.famille}</td>
<td>${item.mageid}</td>
<td>${item.adresse}</td>
<td>${item.fournisseur}</td>
[...]
<td>${item.cau_cli}</td>
<td>${item.maxsst2}</td>
</tr>
`;
});
}
});
} else {
console.log('longueur de terme de recherche insuffisante');
tableOutput.style.display = "none";
appTable.style.display = "block";
}
});
Код JS называет это
view.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()
return JsonResponse(list(data), safe=False)
Моя проблема в том, что ответ содержит Foreignkeys ID, но не значение, установленное в Models str (которое является текстовым значением)
Я думал перестроить ответ querySet, используя промежуточные запросы для извлечения нужных значений, но я хочу знать, существует ли другой "более чистый" метод.
Вы можете получить доступ к значениям связанных полей следующим образом:
products = Produit.objects.filter(...)
data = products.values(
"etat__etat",
"nom",
"famille__nom",
# your other fields here
)
return JsonResponse(list(data), safe=False)
Если вы не хотите, чтобы в вашем ответе были ключи с двойным подчеркиванием (например, etat__etat), вы можете назначить псевдонимы с помощью F-выражений:
from django.db.models import F
...
data = products.values(
"nom",
nom_d_etat=F("etat__etat"),
nom_de_famille=F("famille__nom"),
# your other fields here
)
Обратите внимание, что вы не можете использовать существующее имя поля, т.е. products.values(etat=F("etat__etat") вызовет исключение:
ValueError: The annotation 'etat' conflicts with a field on the model.
Я бы также предложил вам использовать .select_related() в вашем запросе:
products = Produit.objects.filter(...).select_related("etat", "family")
Для полностью альтернативного подхода, вы можете посмотреть в Django REST Framework serializers.