1

I'm currently going around in a bit of a "QuerySet' object has no attribute '' <> app.models.DoesNotExist: Messages matching query does not exist loop.

Essentially, I'm trying to define "last_activity" on a Room model that is referencing the time at which the last Message associated to that room was sent. This is my attempt:

class Room(models.Model):
    title = models.CharField(max_length=255)
    staff = models.BooleanField(default=False)
    slug = models.SlugField(max_length=250, default='')
    banner = models.ImageField(storage=USER_UPLOAD_LOC, null=True, blank=True)

    def last_activity(self):
       last_persisted_message = Messages.objects.filter(where=self.title).order_by('-sent_at')[:1]
       return last_persisted_message.sent_at


class Messages(models.Model):
    room = models.ForeignKey(Room, on_delete=models.CASCADE)
    where = models.CharField(max_length=255)
    message = models.TextField(default='')
    user = models.ForeignKey(settings.AUTH_USER_MODEL)
    username_from = models.CharField(max_length=255)
    username_to = models.CharField(max_length=255, default='all')
    sent_at = models.DateTimeField(default=datetime.datetime.now)

I've tried so many things now and referenced the query set documentation and nothing seems to be working.

I can also confirm that the "where" field for the Messages model is populated when a message is created by {{ room.title }}. I'm using a web socket connection on the client side to pass a "message" back to the websocket consumer.py which then persists the message to the DB).

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
GCien
  • 2,221
  • 6
  • 30
  • 56

1 Answers1

1

If you slice the queryset with [:1] you will obtain a queryset containing at most one item, but not an item itself. You can use [0] to obtain the first item, or, .first():

def last_activity(self):
    last_persisted_message = Messages.objects \
                                     .filter(where=self.slug) \
                                     .order_by('-sent_at') \
                                     .first()
    if last_persisted_message is not None:
        return last_persisted_message.sent_at

If you use [0] and there is no such item, then the program will raise an IndexError (since there is no item with index 0).

In case there is no such Messages object (that satisfies the filter(..)), then last_persisted_message will be None, so you have to find a way to resolve that case. Here we return None in that case.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • I'll accept this as an answer because I think I had it right - I just need where=self.slug (where was the slug field and not the title!) Darn it. Thank you for the prompts tho. – GCien Jan 02 '18 at 23:14