[英]How to recieve not all fields from related(ForeignKey) django model using 'select_related'
[英]Django not showing up all fields using objects with select_related
我在 Django 中遇到了一個煩人的錯誤,我不知道該如何解決。
我正在嘗試使用 INNER JOIN 顯示另一個表中的名稱,但無法正常工作。
澄清一下,我有兩個數據庫canaisAssoc和formatosAssoc ,我試圖從 canaisAssoc 顯示 canais 的名稱,從 formatosAssoc 顯示格式的名稱,如果你看一下我的 views.py,我正在使用ajax,因為我需要從模板中的一個 select 中選擇一個值來填充其他值,問題是,當我運行 canaisAssoc.objects.select_related('idCanal').filter(idSite_id = site, ativo = True).all ()
如果我運行這個
print(channels.query)
查詢的返回是:
SELECT campanhas_canaisassoc
。 id
, campanhas_canaisassoc
。 idSite_id
, campanhas_canaisassoc
。 idCanal_id
, campanhas_canaisassoc
。 ativo
, campanhas_canais_dados
。 id
, campanhas_canais_dados
。 nomeCanais
, campanhas_canais_dados
。 ativo
FROM campanhas_canaisassoc
INNER JOIN campanhas_canais_dados
ON ( campanhas_canaisassoc
= idCanal_id
) WHERE campanhas_canaisassoc
campanhas_canais_dados
ativo
True campanhas_canaisassoc
id
idSite_id
3)
如果我在 phpMyAdmin 中運行它,它們會按預期工作,顯示我需要的所有值
id|idSite_id|idCanal_id|ativo|id| 名稱Canais |ativo
但是,如果我檢查 JSON 的呼叫,他們將返回:
{“頻道”:[{“模型”:“campanhas.canaisassoc”,“pk”:14,“字段”:{“idSite”:3,“idCanal”:13,“ativo”:true}},{“模型”:“campanhas.canaisassoc”,“pk”:15,“字段”:{“idSite”:3,“idCanal”:1,“ativo”:true}},{“模型”:“campanhas.canaisassoc” , "pk": 16, "fields": {"idSite": 3, "idCanal": 4, "ativo": true}}, {"model": "campanhas.canaisassoc", "pk": 17, " fields": {"idSite": 3, "idCanal": 10, "ativo": true}}, {"model": "campanhas.canaisassoc", "pk": 63, "fields": {"idSite": 3, "idCanal": 30, "ativo": true}}]
請注意,在字段中只有 3 個值,idSite、idCanal 和 ativo,我在查詢中無能為力返回 nomeCanais,即使使用 canaisAssoc.objects.raw 和上面的查詢也不起作用,關於我如何做的任何想法解決這個? 下面是我的代碼!
謝謝!
Models.py
class Canais_dados(models.Model):
id = models.AutoField(primary_key=True)
nomeCanais = models.TextField()
ativo = models.BooleanField(default=True)
def __str__(self):
return self.nomeCanais
class Formatos_dados(models.Model):
id = models.AutoField(primary_key=True)
nomeFormato = models.TextField()
ativo = models.BooleanField(default=True)
def __str__(self):
return self.nomeFormato `Preformatted text`
class canaisAssoc(models.Model):
id = models.AutoField(primary_key=True)
idSite = models.ForeignKey(Sites_dados, on_delete=models.CASCADE, related_name='idSitesCanaisAssoc',null=False)
idCanal = models.ForeignKey(Canais_dados, on_delete=models.CASCADE, related_name='idCanaisCanaisAssoc',null=False)
ativo = models.BooleanField(default=True,null=True)
class formatosAssoc(models.Model):
id = models.AutoField(primary_key=True)
idSite = models.ForeignKey(Sites_dados, on_delete=models.CASCADE, related_name='idSiteFormatoAssoc',null=False)
idFormato = models.ForeignKey(Formatos_dados, on_delete=models.CASCADE, related_name='idFormatoFormatoAssoc',null=False)
ativo = models.BooleanField(default=True,null=True)
views.py
# AJAX
def load_channel(request,site):
channels = canaisAssoc.objects.select_related('idCanal').filter(idSite_id = site, ativo = True).all()
formats = formatosAssoc.objects.select_related('idFormato').filter(idSite_id = site,ativo = True).all()
channelName = serialize("json",channels)
serializedChannel = json.loads(channelName)
formatName = serialize("json",formats)
serializedFormat = json.loads(formatName)
return JsonResponse({'formats':serializedFormat,'channel': serializedChannel})
我嘗試了 objects.raw,即使那樣也沒有按預期工作。
我期待 JSON 返回類似的東西:
{“頻道”:[{“模型”:“campanhas.canaisassoc”,“pk”:14,“字段”:{“idSite”:3,“idCanal”:13,“ativo”:真,“nomeCanais”: “Y 運河”}},{“模型”:“campanhas.canaisassoc”,“pk”:15,“字段”:{“idSite”:3,“idCanal”:1,“ativo”:true,“nomeCanais” :“CanalXX”}},{“模型”:“campanhas.canaisassoc”,“pk”:16,“字段”:{“idSite”:3,“idCanal”:4,“ativo”:true,“nomeCanais” :“CanalXXY”}},{“模型”:“campanhas.canaisassoc”,“pk”:17,“字段”:{“idSite”:3,“idCanal”:10,“ativo”:true,“nomeCanais” :“CanalXXYZ”}},{“模型”:“campanhas.canaisassoc”,“pk”:63,“字段”:{“idSite”:3,“idCanal”:30,“ativo”:true,“nomeCanais” : "CanalXXYZ"}}]
您誤解了select_related
的工作原理。 它的目的是減少為相關模型獲取數據的數據庫請求量,而不是更改它們的字段。
考慮例子:
class ModelA(models.Model):
a_data = ... # example field
... # other-fields
class ModelB(models.Model):
a_object = models.ForeignKey(ModelA, ...)
b_data = ... # example field
... # other-fields
沒有select_related
:
b_objects = ModelB.objects.all() # first request
for b in b_objects:
a = b.a_object # +1 request for each a_object.
a_data = a.a_data # get a_data.
b_data = b.b_data # get b_data.
... # do something.
這里第一個請求從 ModelB 的表中獲取數據。 然后,對於每個a_object
,都會向 ModelA 的表發出一個額外的請求。
使用select_related
:
b_objects = ModelB.objects.select_related('a_object') # first request.
for b in b_objects:
a = b.a_object # no extra requests.
a_data = a.a_data # get a_data.
b_data = b.b_data # get b_data.
... # do something.
這里第一個請求一次性獲取 ModelB 和相關的 ModelA 的數據。 沒有額外的要求。 但是您從代碼中訪問該數據的方式並沒有改變。
有關詳細信息,請參閱select_related上的文檔。
反向或 m-2-m 關系的類似方法: prefetch_related 。
b_objects = ModelB.objects.values(
'pk', # b's own fields
'b_data', # b's own fields
'a_object__pk', # related a_object's fields
'a_object__a_data', # related a_object's fields
... # other fields
)
這將返回一個字典查詢集,如下所示:
<QuerySet [
{'pk': 1, 'b_data': 'b_1', 'a_object__pk': 1, 'a_object__a_data': 'a_1'},
{'pk': 2, 'b_data': 'b_2', 'a_object__pk': 2, 'a_object__a_data': 'a_2'},
...]>
然后您可以在序列化之前對其進行序列化或轉換為更原始的數據類型。
類似的方法values_list返回沒有鍵的值列表:
<QuerySet [
[1, 'b_1', 1, 'a_1'],
[2, 'b_2', 2, 'a_2'],
...]>
b_objects = ModelB.objects.annotate(
a_pk = F('a_object__pk'), # add a_object's pk as 'a_pk'
a_data = F('a_object__data'), # add a_object's a_data as 'a_data'
)
它將額外的屬性添加到具有相關a
對象的相應值的b
對象。
將其與values
相結合,為鍵提供更短的名稱:
b_objects = ModelB.objects.annotate(
a_pk = F('a_object__pk'), # add a_object's pk as 'a_pk'
a_data = F('a_object__data'), # add a_object's a_data as 'a_data'
).values(
'pk', # b's own fields
'b_data', # b's own fields
'a_pk', # annotated fields
'a_data', # annotated fields
...
)
出於安全原因,不建議使用Raw 。
對於大於 1-2 個端點的 API,還可以考慮使用DRF 。 它就是為此而制作的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.