Reputation: 555
Say I have such models in Django:
class User(models.Model):
name=models.CharField(...)
email=models.EmailField(...)
photo=...
<other fields>
class Comment(models.Model):
user=models.ForeignKey(User, ...)
I have a function that receives Comment object and needs just name and email fields to send email (it is just example, obvious)
def sendEmail(comment):
name, email=comment.user.name, comment.user.email
In implementation presented above, Django will fetch all fields of related object User (something roughly equal to select * from users where id=comment.user_id
)
Using values_list I can fetch just needed fields:
Users.objects.filter(id=comment.user_id).values_list('name', 'email')
but values_list only applicable to QuerySet object, not to model instance.
My question is: is there any way to do the same thing using only "comment" object?
It must be equal to
select name, email from users where id=comment.user_id
by complexity (I don't want to transfer a lot of data stored in some fields over network when I don't need it)
Upvotes: 20
Views: 24874
Reputation: 63
queryset = ModelName.objects.filter().only('realed_obj__field1', 'related_obj__field2')
Upvotes: 2
Reputation: 138
Users.objects.filter(id=comment.user_id).values_list('name', 'email').get()
That should do
Upvotes: 1
Reputation: 19831
It must be equal to
select name, email from users where id=comment.user_id
by complexity.
What is really equivalent to this query is what you already have:
Users.objects.filter(id=comment.user_id).values_list('name', 'email')
... but
values_list
only applicable toQuerySet
object, not to model instance.
That is absolutely right. but what you need to consider is that once you have this queryset you can get the first element because with one user id there will just be one user:
name, email = Users.objects.filter(id=comment.user_id).values_list('name', 'email').first()
Upvotes: 0
Reputation: 6013
If you want to have comments with some additional user data, without having to retrieve whole User
objects I believe it's better to fetch additional data when you fetch the comments:
Comment.objects.filter(user=user).values_list('user__name', 'user__email')
Obviously you can fetch other useful Comment
fields.
OR:
Comment.objects.filter(user=user).annotate(author_name=F('user__name'),\
author_email=F('user__email'))
This still uses the QuerySet
API, but both approaches allow you to span relationships to get additional data without extra queries.
Upvotes: 16