Django:在 ajax 搜索结果中获取(模型)__str__ 外键(文本)值而不是其 ID
Django : Get (models) __str__ foreignkey (text) value instead of its ID in ajax search result
我用 JS 是这样搜索产品的:
models.py(摘要)
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)
我的问题是响应包含外键 ID,但不包含模型 str 中设置的值(这是一个文本值)
虽然我想使用中间查询重建 querySet 响应以检索所需的值,但我想知道之前是否存在另一种“更清洁”的方法。
编辑:
等待 VIEWS.PY 中更好的解决方案,我迭代每个结果并在数据库中请求“文本”。我以为它会慢很多,但是没有。
if len(data) > 0:
for i in range(len(data)):
etat = Etat.objects.get(pk=data[i]
['etat_id']).etat
famille = Famille.objects.get(pk=data[i]
['famille_id']).nom
fournisseur = Supplier.objects.get(
pk=data[i]['fournisseur_id']).nom
data[i]['etat_id'] = etat
data[i]['famille_id'] = famille
data[i]['fournisseur_id'] = fournisseur
return JsonResponse(list(data), safe=False)
我知道它不是很干净,但暂时还行
您可以像这样访问相关字段的值:
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。
我用 JS 是这样搜索产品的:
models.py(摘要)
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)
我的问题是响应包含外键 ID,但不包含模型 str 中设置的值(这是一个文本值)
虽然我想使用中间查询重建 querySet 响应以检索所需的值,但我想知道之前是否存在另一种“更清洁”的方法。
编辑:
等待 VIEWS.PY 中更好的解决方案,我迭代每个结果并在数据库中请求“文本”。我以为它会慢很多,但是没有。
if len(data) > 0:
for i in range(len(data)):
etat = Etat.objects.get(pk=data[i]
['etat_id']).etat
famille = Famille.objects.get(pk=data[i]
['famille_id']).nom
fournisseur = Supplier.objects.get(
pk=data[i]['fournisseur_id']).nom
data[i]['etat_id'] = etat
data[i]['famille_id'] = famille
data[i]['fournisseur_id'] = fournisseur
return JsonResponse(list(data), safe=False)
我知道它不是很干净,但暂时还行
您可以像这样访问相关字段的值:
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。