bdemirka
bdemirka

Reputation: 837

Is there a way to serialize multiple objects in Django?

In a Django Project I would like to implement a simple chat-box.

Version

Django version 3.0.8

Models.py

class DirectMessageClass(models.Model):  
sender = models.ForeignKey(User, on_delete=models.CASCADE,
                             related_name='from_this')
receiver = models.ForeignKey(User, on_delete=models.CASCADE,
                              related_name='to_this')
timestamp = models.DateTimeField(auto_now=True)
content = models.CharField(max_length=200)
read = models.BooleanField(default=False)

def serialize(self):
    return {
        "id": self.id,
        "sender": self.sender.username,
        "sendername":self.sender.profile.firstname,
        "senderimage":self.sender.profile.image.url,
        "receiver": self.receiver.username,
        "content": self.content,
        "timestamp":self.timestamp.strftime("%m/%d/%Y, %H:%M:%S"), # to format date
        "read":self.read,
    }

Views.py

def loadbox(request):
user = request.user 
# Return messages in reverse chronologial order
messages = DirectMessageClass.objects.filter(receiver=user).order_by("-timestamp").all()
return JsonResponse([message.serialize() for message in messages], safe=False)

I successfully get messages and turn it into a JSON object in the /loadbox path with this method. Later on, I fetch this data to display messages and it works.

Example of my /loadbox path

[{"id": 1, "sender": "ekvatorcizgisi", "sendername": "Asli", 
  "receiver": "bilge", "content": "hi", "timestamp": "09/02/2020, 08:22:26", "read": true}]

   

However, because I want it to display as a dialog. I need to add also the reply messages in this JSON object.

In views.py I try

def loadbox(request):
user = request.user 
# Return messages in reverse chronologial order
messages = DirectMessageClass.objects.filter(receiver=user).order_by("-timestamp").all()
# return replies sent by the current user
replies = DirectMessageClass.objects.filter(sender=user).order_by("-timestamp").all()
return JsonResponse([message.serialize() for message in messages], safe=False)

I am not sure how to return multiple Json response in the /loadbox path

return JsonResponse([message.serialize() for message in messages,reply.serialize() for reply in replies], safe=False)

gives syntax error obviously, (SyntaxError: invalid syntax) I also tried the put it all in a list but couldn't make it work.

My ideal output is

 [messages: {"id": 1, "sender": "ekvatorcizgisi", "sendername": "Asli", 
  "receiver": "bilge", "content": "hi", "timestamp": "09/02/2020, 08:22:26", "read": true}
  replies:{"id": 3, "sender": "bilged", "sendername": "bilge", 
  "receiver": "Asli", "content": "hi there", "timestamp": "09/02/2020, 08:22:26", "read": false}]

Maybe I would do another path for reply messages to solve this problem, but I wonder is there any better way to do this?

Upvotes: 2

Views: 193

Answers (1)

JPG
JPG

Reputation: 88509

Use list up-packing technique

def loadbox(request):
    # rest of your code
    return JsonResponse(
        [
            *[message.serialize() for message in messages],
            *[reply.serialize() for reply in replies]
        ],
        safe=False
    )

Simple demonstration:

In [1]: foo = [1,2,3]                                                                                                                                                                                              

In [2]: bar = [5,6,7]                                                                                                                                                                                              

In [3]: foo_bar = [*foo,*bar]                                                                                                                                                                                      

In [4]: foo_bar                                                                                                                                                                                                    
Out[4]: [1, 2, 3, 5, 6, 7]

Upvotes: 2

Related Questions