Запрос Django ORM для системы обмена сообщениями - PullRequest
1 голос
/ 31 октября 2011

У меня есть следующие модели для приложения внутреннего обмена сообщениями:

class MessageThread(models.Model):
    subject = models.CharField(max_length=256, blank=False)

class Message(models.Model):
    thread = models.ForeignKey(MessageThread)
    content = models.CharField(max_length=5000, blank=False)
    timestamp = models.DateTimeField(auto_now_add=True, blank=False)
    sender = models.ForeignKey(User)

class MessageRecipient(models.Model):
    message = models.ForeignKey(Message)
    thread = models.ForeignKey(MessageThread)
    recipient = models.ForeignKey(User)
    status = models.CharField(max_length=20, choices=MESSAGE_STATUS, default="unread")

Для данного пользователя, чтобы получить список потоков, которые я делаю:

distinct_threads=MessageThread.objects.filter(messagerecipient__recipient=user)
    .order_by('-message__timestamp').distinct()

Как бы мне избавиться от всех тем с сообщением, которое содержит статус «удален» в ORM? (Другими словами, я хочу получить список всех потоков без потока, содержащего сообщение со статусом = "удалено".)

Ответы [ 3 ]

1 голос
/ 31 октября 2011

Я добавил метод в менеджере моделей для этого:

    def get_active_threads(self, user):
        all_threads = MessageRecipient.objects.filter(recipient=user).order_by('-message__timestamp')

        deleted_threads = []
        final_threads = []

        for thread in all_threads:
            if thread.thread not in (deleted_threads or final_threads):
                if thread.status == "deleted":
                    deleted_threads.append(thread.thread)
                else:
                    final_threads.append(thread)

        return final_threads
1 голос
/ 31 октября 2011

Вы можете сделать это на python (как предложено выше) или позволить БД сделать за вас грязную работу.

Вам потребуется создать QuerySet, содержащий все потоки с удаленным сообщением для конкретного пользователя, а затем второй QuerySet, который получает все потоки, не содержащиеся в первом:

delthreads = MessageThread.objects.filter(messagerecipient__recipient=user,
    messagerecipient__status='deleted').distinct()
result = MessageThread.objects.filter(messagerecipient_recipient=user)
    .exclude(messagethread_in=delthreads).distinct()

Однако, с точки зрения производительности (особенно на больших столах) это повредит вам. Ваша модель нуждается в некоторой реструктуризации для обеспечения более эффективных запросов Рассмотрим:

class MessageThread(models.Model):
    subject = models.CharField(max_length=256, blank=False)

class Message(models.Model):
    thread = models.ForeignKey(MessageThread)
    content = models.CharField(max_length=5000, blank=False)
    timestamp = models.DateTimeField(auto_now_add=True, blank=False)
    sender = models.ForeignKey(User)
    recipient = models.ForeignKey(User)
    status = models.CharField(max_length=20, choices=MESSAGE_STATUS, default="unread")

Если вы ожидаете, что вы будете часто выполнять этот запрос, вы можете добавить поле кэша в MessageThread, которое вы можете обновлять всякий раз, когда кто-то удаляет сообщение в этой теме:

class MessageThread(models.Model):
    subject = models.CharField(max_length=256, blank=False)
    dirty = models.BooleanField(default=False)

Тогда было бы очень легко извлечь список тем без удаленных сообщений.

nondelthreads = MessageThread.objects.filter(message__recipient=user, dirty=True).distinct()
0 голосов
/ 31 октября 2011

Как быстро, почему у вас есть thread как поле в MessageRecipient?Вы можете добраться до thread через message.

В любом случае вам необходимо использовать exclude ()

# breaking up onto multiple lines for readability, not valid python though
MessageThread.objects.filter(messagerecipient__recipient=user)
.exclude(messagerecipient__status='deleted')
.order_by('-message__timestamp').distinct()
...