根据相关对象查找对象

时间:2013-03-25 22:12:38

标签: django django-models

我正在尝试使用Django构建消息传递应用程序。我不使用postman的原因是我需要在除用户之外的其他对象之间进行消息传递,而且我不需要大多数邮递员的功能。

以下是我的模特:

class Recipient(models.Model):
    ...
    def get_unread_threads():
        see below...


class Thread(models.Model):
    author = models.ForeignKey(Recipient, related_name='initiated_threads')
    recipients = models.ManyToManyField(
        Tribe,
        related_name='received_thread',
        through='ThreadReading')
    subject = models.CharField(max_length=64)

    class Meta:
        app_label = 'game'


class Message(models.Model):
    author = models.ForeignKey(Recipient, related_name='sent_messages')
    date_add = models.DateTimeField(auto_now_add=True)
    date_edit = models.DateTimeField(blank=True)
    content = models.TextField(max_length=65535)
    thread = models.ForeignKey(Thread)

    class Meta:
        get_latest_by = 'date'


class ThreadReading(models.Model):
    thread = models.ForeignKey(Thread)
    recipient = models.ForeignKey(Recipient)
    date_last_reading = models.DateTimeField(auto_now=True)

我的问题是关于get_unread_threads。我真的不知道该怎么做。这是第一次尝试:

def get_unread_threads(self):
    """
    return a queryset corresponding to the threads
    which at least one message is unread by the recipient
    """
    try:
        query = self.received_thread.filter(
                message__latest__date_add__gt=\
                        self.threadreading_set.get(thread_id=F('id')).date_last_reading) 
    except ObjectDoesNotExist:
        query = None
    return query

但显然它不起作用,因为查找不能遵循方法latest

1 个答案:

答案 0 :(得分:2)

你走了:

# Get all the readings of the user
thread_readings = recipient.threadreading_set.all()

# Build a query object including all messages who's last reading is after the
# last edit that was made AND whose thread is the thread of the current
# iteration's thread reading
q = models.Q()
for thread_reading in thread_readings:
    q = q | models.Q(
        models.Q(
            date_edit__lte=thread_reading.date_last_reading
            & models.Q(
                thread=thread_reading.thread
            )
        )
    )

# Get a queryset of all the messages, including the threads (via a JOIN)
queryset = Message.objects.select_related('thread')

# Now, exclude from the queryset every message that matches the above query
# (edited prior to last reading) OR that is in the list of last readings
queryset = queryset.exclude(
    q | models.Q(
        thread__pk__in=[thread_reading.pk for thread_reading in thread_readings]
    )
)

# Make an iterator (to pretend that this is efficient) and return a generator of it
iterator = queryset.iterator()
return (message.thread for message in iterator)

:)

现在,不要真的这样做 - 重新考虑你的模特。我会读一本名为“面向对象的分析和应用程序设计”的书。它会教你如何在数据建模时思考。