1

我正在尝试使用 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

4

1 回答 1

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)

:)

现在,永远不要这样做——重新考虑你的模型。我会读一本名为“面向对象的分析和设计与应用程序”的书。它会教你很多关于在数据建模时如何思考的知识。

于 2013-03-27T04:47:43.103 回答