2016-10-25 2 views
0

Мой вопрос прост: в приложении Django у меня есть таблица Users и таблица StatusUpdates. В таблице StatusUpdates у меня есть столбец user, который является внешним ключом, указывающим на Users. Как я могу сделать поиск выразить что-то вроде:Django: Как фильтровать внутреннее соединение на основе свойств второй таблицы?

users.filter(latest_status_update.text__contains='Hello') 

Edit:

Пожалуйста, простите мое отсутствие ясности. Запрос, который я хотел бы сделать, это что-то вроде «Дайте мне всех пользователей, чье обновление содержит текст« hello ». В Django коде, я хотел бы сделать следующее (что на самом деле неэффективно и некрасиво):

hello_users = [] 
for user in User.objects.all(): 
    latest_status_update = StatusUpdate.objects.filter(user=user).order_by('-creation_date')[0] 
    if latest_status_update.text.contains('Hello'): 
    hello_users.append(user) 

return hello_users 

Edit 2:

Я уже нашел решение, но так как я был задан вопрос, здесь являются важные части моих моделей:

class User(models.Model): 
    ... 

class StatusUpdate(models.Model): 
    user = models.ForeignKey(User) 
    text = models.CharField(max_length=140) 
    creation_date = models.DateTimeField(auto_now_add=True, editable=False) 
    .... 

ответ

2

Хорошо, я думаю, что я получил это:

from django.db.models import Max, F 

User.objects\ 
    .annotate(latest_status_update_id=Max('statusupdate__id'))\ 
    .filter(
    statusupdate__id=F('latest_status_update_id'), 
    statusupdate__text__icontains='hello' 
) 

Для получения дополнительной информации см this section of the Django documentation.

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

0

Не уверен, что я понимаю, что вы пытаетесь сделать что-то вроде

StatusUpdates.objects.select_related("user").filter(text__contains = "hello").order_by("-updated").first() 

Это вернет StatusUpdate, который был изменен последним (если у вас есть обновленное поле, в котором хранится время последней модификации), которое содержит «Hello» в текстовом поле. Если ни один из StatusUpdates не содержит эту строку, он вернет None.

Затем вы можете сделать

latest = StatusUpdates.objects.select_related("user").filter(text__contains = "hello").order_by("-updated").first() 
#then if you needed the user too 
if latest is not None: 
    user = latest.user #which does not call the DB again since you selected related` 

Если это не то, что вам нужно, пожалуйста, предоставьте более подробную информацию (модели) и уточнить вашу потребность

+0

Спасибо за ваш ответ. Я уточнил вопрос, чтобы быть более ясным. – daveslab

0
latest_status_updates = filter(lambda x: x.text.contains('hello'), 
    [ 
     user.statusupdates_set.order_by('-creation_date').first() 
     for user in User.objects.all() 
    ] 
) 
users = list(set([status_update.user for status_update in latest_status_updates])) 

EDIT: Теперь я сначала получить все ПОСЛЕДНИЕ обновления статуса каждого пользователя в список, который затем фильтруется текстовым полем, найденным в классе StatusUpdate. Во второй строке я извлекаю пользователей из фильтрованных обновлений статуса, а затем создаю уникальный список пользователей.

Надеюсь, это поможет!

+0

В вашем запросе не учитывается тот факт, что я хочу выполнить поиск по ** обновлению ** ** ** для каждого пользователя **. Кроме того, ваш список пользователей не будет уникальным. – daveslab

+0

Пожалуйста, ознакомьтесь с изменениями и дайте мне знать, если есть проблема :) –

Смежные вопросы