2017-08-29 3 views
0

J'ai ces modèles:accès à des champs d'une relation inverse dans django

class Task(models.Model): 
    user = models.ForeignKey(User) 
    name = models.CharField() 

class Report(models.Model): 
    task = models.ForeignKey(
     Task, blank=True, null=True, related_name='+') 
    status = models.CharField(max_length=32, choices=Status.CHOICES, default=Status.INCOMPLETE) 

Maintenant, je veux obtenir tous les Task s et leur statut connexe.

Comment faire?

+1

ça va être difficile quand vous avez explicitement désactivé la relation inverse dont vous avez besoin en spécifiant 'related_name = '+''. sinon voir les docs https://docs.djangoproject.com/fr/1.11/topics/db/queries/#backwards-related-objects – Anentropic

Répondre

1

Dans un premier temps, '+' n'est pas un related_name valide. Ce n'est pas très explicite.

Essayez de remplacer '+' avec 'reports' à la place:

# ... 

class Report(models.Model): 
    task = models.ForeignKey(
     Task, 
     blank=True, 
     null=True, 
     related_name='reports' # <<< 
    ) 
    status = models.CharField(
     max_length=32, 
     choices=Status.CHOICES, 
     default=Status.INCOMPLETE 
    ) 

Ensuite, pour obtenir toutes les Task s avec leur statut lié, vous pouvez utiliser values:

>>> Task.objects.values('name', 'report__status') 
<QuerySet [{'name': 'test', 'report__status': 'OK'}, ...]> 
0

Modifiez la valeur de related_name à quelque chose d'autre, comme 'reports' par exemple:

class Report(models.Model): 
    task = models.ForeignKey(
     Task, blank=True, null=True, related_name='reports') 
    status = models.CharField(max_length=32, choices=Status.CHOICES, default=Status.INCOMPLETE) 

Maintenant, si vous avez un objet de tâche (non queryset), vous pouvez obtenir un queryset de c'est des rapports en utilisant:

reports = task.reports.all()

Vous pouvez utiliser filter() sur le reports si vous le souhaitez.

reports = task.reports.filter(status='something')

0

Le signe + est exactement ce que vous ne ne veulent pas avoir comme related_name dans ce cas. Il dit à Django de ne pas créer de relation en arrière. Découvrez here. Choisissez un autre nom valide ou ignorez cet argument, auquel cas Django créera une relation inverse par défaut en utilisant pour le nom de la relation descendante le nom du modèle en minuscules et le suffixe _set (voir here pour plus de détails).

Cependant, dans votre exemple, si vous souhaitez obtenir tous les rapports liés à une tâche et l'état correspondant, vous n'avez pas nécessairement besoin de relations descendantes. Essayez ceci:

reports = Report.objects.exclude(task__isnull=True).values('task__name', 'status')