2017-09-23 7 views
0

je ces deux modèles:Obtenir des informations à partir d'un modèle en utilisant autre domaine

class A(models.Model): 
    name=models.CharField(max_length=10) 

class D(models.Model): 
    code=models.IntegerField() 

le champ de code peut avoir un numéro qui existe dans le modèle A, mais il ne peut pas être liée à d'autres facteurs. Mais ce que je veux savoir est à la liste des articles de A dont la valeur est la même avec le code

items=D.objects.values('code__name') 

fonctionnerait, mais étant donné qu'ils ne sont pas liés et ne peuvent être liés, comment puis-je gérer cela?

+0

Le champ de code peut avoir un nombre qui existe dans le modèle A - que voulez-vous dire? code == pk dans le modèle A? –

+0

@BearBrown Oui, il contient un nombre qui existe dans le modèle A –

Répondre

1

vous pouvez utiliser django extra, remplacer YOUAPP sur votre nom d'application

D.objects.extra(select={'a_name': 'select name from YOUAPP_a where id=code'}).values('a_name') 
#           Replace YOUAPP^^^^^ 
+0

+1: parce que la méthode '.extra()' était nécessaire il y a peu de temps avant Django 1.11, mais elle est associée à un avertissement de sécurité et une note "Utiliser cette méthode comme Un dernier recours." (docs). Mon expérience est qu'il a eu beaucoup de limitations et de conséquences inattendues, y compris "Replace YOUAPP". Je ressens de nouvelles classes d'expression de requête très sympathiques. – hynekcer

+0

Si vous utilisez '.values ​​('a_name')' alors le résultat n'a que ce champ. C'est inutile. (Peut être réparé facilement de plusieurs façons Oui, parfois les noms de champs doivent être répétés en valeurs.) C'est pourquoi je voulais dire que les règles d'utilisation de la méthode extra() ne sont pas faciles à mémoriser même après une longue expérience. – hynekcer

0

Vous pouvez utiliser Subquery() expressions dans Django 1.11 ou plus récent.

from django.db.models import OuterRef, Subquery 

code_subquery = A.objects.filter(id=OuterRef('code')) 
qs = D.objects.annotate(code_name=Subquery(code_subquery.values('name'))) 

La sortie de qs est un queryset d'objets D avec un champ ajouté code_name.


Notes:

Il est compilé à un SQL très similaire (comme la solution de l'ours brun avec la méthode "extra", mais sans les inconvénients de sa solution, voir là):

SELECT app_d.id, app_d.code, 
     (SELECT U0.name FROM app_a U0 WHERE U0.id = (app_d.code)) AS code_name 
FROM app_d 

Si une sortie de dictionnaire est requise, elle peut être convertie par .values() enfin. Il peut fonctionner comme une jointure gauche, c'est-à-dire si le pseudo-champ associé autorise null (code = models.IntegerField(none=True)) alors les objets D ne sont pas restreints et la valeur de nom_de_codes de sortie peut être None. Une caractéristique de Subquery est qu'il retourne une seule expression de champ doit être finalement répété pour d'autres champs. (Cela est similaire à extra(select={...: "SELECT ..."}), mais grâce à la syntaxe de l'objet, il peut être plus facile à lire qu'un SQL explicite.)