2016-12-12 2 views
4

sagen, dass ich solche Modelle in Django haben:Holen Sie nur bestimmte Felder von verwandten Objekt in Django

class User(models.Model): 
    name=models.CharField(...) 
    email=models.EmailField(...) 
    photo=... 
    <other fields> 

class Comment(models.Model): 
    user=models.ForeignKey(User, ...) 

Ich habe eine Funktion, die Kommentar-Objekt empfängt und Namen und E-Mail-Felder muss nur E-Mail zu senden (es ist nur Beispiel , offensichtlich)

def sendEmail(comment): 
    name, email=comment.user.name, comment.user.email 

In Implementierung oben dargestellt, wird Django alle Bereiche der zugehörigen Benutzerobjekt (etwas in etwa gleich select * from users where id=comment.user_id) Mit values_list hole ich gerade benötigten Felder holen kann:

Users.objects.filter(id=comment.user_id).values_list('name', 'email')

aber values_list nur für QuerySet Objekt, beispielsweise zur Modellierung nicht. Meine Frage ist: Gibt es eine Möglichkeit, die gleiche Sache mit nur "Kommentar" -Objekt zu tun? Es muss select name, email from users where id=comment.user_id durch Komplexität gleich sein (ich will nicht viele Daten in einigen Bereichen über das Netzwerk gespeichert übertragen, wenn ich es nicht brauchen)

+1

Also kurz gesagt, würden Sie die 'ForeignKey' gerne holen das verwandte Objekt nur teilweise ohne die Notwendigkeit eines * expliziten * Querysets? – dhke

+0

@dhke, ja, genau – fantom

+0

Ehrlich gesagt: Hand 'Comment' eine Eigenschaft, die das Ergebnis der obigen Abfrage zurückgibt. Andere Lösungen, die ich erhalte, enden alle in 'contribute_to_class()' mit einem benutzerdefinierten [ForwardManyToOneDescriptor] (https://github.com/django/django/blob/8db6a6c0a1c73bf08e71e00d4ab8c4af3c5f0cb8/django/db/models/fields/related_descriptors.py# L78) und das ist nur Overkill. – dhke

Antwort

2

Wenn Sie Kommentare mit einigen zusätzlichen Benutzer haben wollen Daten, ohne ganze User Objekte abzurufen, die ich glaube, es ist besser, um zusätzliche Daten zu holen, wenn Sie die Kommentare zu holen:

Comment.objects.filter(user=user).values_list('user__name', 'user__email') 

Natürlich können Sie andere nützliche Comment Felder holen.

OR:

Comment.objects.filter(user=user).annotate(author_name=F('user__name'),\ 
              author_email=F('user__email')) 

Dies nutzt noch die QuerySet API, aber beide Ansätze ermöglichen es Ihnen, Beziehungen zu überbrücken, ohne zusätzliche Abfragen zusätzliche Daten zu erhalten.

0

Es muss select name, email from users where id=comment.user_id durch Komplexität gleich sein.

Was auf diese Frage wirklich gleichwertig ist, was Sie bereits haben:

Users.objects.filter(id=comment.user_id).values_list('name', 'email') 

... aber values_list nur für QuerySet Objekt, nicht Instanz zu modellieren.

Das ist absolut richtig. aber was müssen Sie zu beachten ist, dass, sobald Sie diese queryset haben, können Sie das erste Element erhalten, weil mit einem Benutzer-ID wird es nur ein Benutzer sein:

name, email = Users.objects.filter(id=comment.user_id).values_list('name', 'email').first() 
+0

Es ist eine schlechte Idee, 'first' und Tuple Expansion zusammen zu verwenden. Wenn nichts passt, wird ein Fehler angezeigt, weil' None' nicht in zwei Teile aufgeteilt werden kann. – Shadow

Verwandte Themen