Вопрос: Получить только определенные поля связанного объекта в Django


Скажем, у меня такие модели в Django:

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

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

У меня есть функция, которая получает объект Comment и требует только полей имени и электронной почты для отправки электронной почты (это просто пример, очевидный)

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

В реализации, представленной выше, Django будет извлекать все поля связанного объекта User (примерно примерно равное select * from users where id=comment.user_id) Используя values_list, я могу получить только нужные поля:

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

но values_list применим только к объекту QuerySet, а не к экземпляру модели. Мой вопрос: есть ли способ сделать то же самое, используя только объект «comment»? Он должен быть равен select name, email from users where id=comment.user_id по сложности (я не хочу передавать много данных, хранящихся в некоторых полях по сети, когда мне это не нужно)


4


источник


Ответы:


Если вы хотите иметь комментарии с некоторыми дополнительными пользовательскими данными, без необходимости получать целые User объекты Я считаю, что лучше извлекать дополнительные данные при получении комментариев:

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

Очевидно, вы можете получить другие полезные Comment поля.

ИЛИ ЖЕ:

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

Это все еще использует QuerySet API, но оба подхода позволяют вам охватывать отношения для получения дополнительных данных без дополнительных запросов.


2



Он должен быть равен select name, email from users where id=comment.user_id по сложности.

То, что действительно эквивалентно этому запросу, - это то, что у вас уже есть:

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

... но values_list применимо только к QuerySet объект, а не образец экземпляра.

Это абсолютно правильно. но то, что вам нужно учитывать, это то, что, как только у вас есть этот запрос, вы можете получить первый элемент, потому что с одним идентификатором пользователя будет только один пользователь:

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

0



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

Это должно сделать


0