简体   繁体   English

Django - 如何在发送消息后显示用户的个人资料图片?

[英]Django - How to display user's profile picture with a message after its sent?

I have a live chat application and I'm trying to display a profile picture with the message after its sent with Javascript.我有一个实时聊天应用程序,我试图在使用 Javascript 发送消息后显示带有消息的个人资料图片。 Here is my code...这是我的代码...

Models.py - here is my Message and Profile model Models.py - 这是我的消息和个人资料模型

class Message(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    room = models.CharField(max_length = 255)
    content = models.TextField()
    date_added = models.DateTimeField(auto_now_add = True)

    class Meta:
        ordering = ('date_added', )

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    image = models.ImageField(default='default.png', upload_to='profile_pics')

    def __str__(self):
        return f'{self.user.username} Profile'

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

        img = Image.open(self.image.path)

        if img.height > 300 or img.width > 300:
            output_size = (300, 300)
            img.thumbnail(output_size)
            img.save(self.image.path)

Consumers.py消费者.py

class ChatRoomConsumer(AsyncWebsocketConsumer):
async def connect(self):
    self.room_name = self.scope['url_route']['kwargs']['room_name']
    self.room_group_name = 'chat_%s' % self.room_name
    print(self.room_group_name)

    await self.channel_layer.group_add(
        self.room_group_name,
        self.channel_name
    )

    await self.accept()

async def disconnect(self, close_code):
    await self.channel_layer.group_discard(
        self.room_group_name,
        self.channel_name
    )

async def receive(self, text_data):
    text_data_json = json.loads(text_data)
    message = text_data_json['message']
    username = text_data_json['username']
    room = text_data_json['room']

    await self.save_message(username, room, message)

    await self.channel_layer.group_send(
        self.room_group_name,
        {
            'type': 'chatroom_message',
            'message': message,
            'username': username,
        }
    )

async def chatroom_message(self, event):
    message = event['message']
    username = event['username']

    await self.send(text_data=json.dumps({
        'message': message,
        'username': username,
    }))

@sync_to_async
def save_message(self, username, room, message):
    user = User.objects.get(username = username)
    Message.objects.create(author = user, room = room, content = message)

pass

And here is the Javascript code for the live chat...这是实时聊天的Javascript代码...

{{ request.user.username|json_script:"user_username" }}
{{ room_name|json_script:"room-name" }}
<script>
    const user_username = JSON.parse(document.getElementById('user_username').textContent);
    document.querySelector('#submit').onclick = function (e) {
        const messageInputDom = document.querySelector('#input');
        const message = messageInputDom.value;
        if(message.trim() == ''){
        }
        else {
            chatSocket.send(JSON.stringify({
            'message': message,
            'username': user_username,
            'room': roomName,
        }));
        messageInputDom.value = '';
        }
    };
    const roomName = JSON.parse(document.getElementById('room-name').textContent);

    const chatSocket = new WebSocket(
        'ws://' +
        window.location.host +
        '/ws/chat/' +
        roomName +
        '/'
    );

    chatSocket.onmessage = function (e) {
        const data = JSON.parse(e.data);
        console.log(data)
        if (data.message) {
                document.querySelector('#chat-text').innerHTML += ('<img id="imageid" src="{{ message.author.profile.image.url }}">' + data.username + '<br>' + data.message + '<br>');
            }
        else {

        }
    }
</script>

The problem is with this <img id="imageid" src="{{ message.author.profile.image.url }}"> in the Javascript code.问题在于Javascript代码中的<img id="imageid" src="{{ message.author.profile.image.url }}"> So my question is, how can I display the user's profile picture with the message after its sent without refreshing the page?所以我的问题是,如何在不刷新页面的情况下在消息发送后显示用户的个人资料图片?

您可以使用 Ajax 仅刷新网页的一部分,使用不同的 HTML 文档,其中包含用于显示个人资料图片的 Django HTML。

You don't need to use AJAX here, you are communicating with the server via WebSockets, you can get the data you need through it.这里不需要使用AJAX,你是通过WebSockets与服务器通信,通过它就可以得到你需要的数据。

Looks like you are using django-channels.看起来您正在使用 django-channels。 Check django-channels documentation about authentication .检查有关身份验证的django-channels 文档 If you enable it, you will be able to access the current user through self.scope['user'] .如果启用它,您将能够通过self.scope['user']访问当前用户。

So, you will able to do something like this:因此,您将能够执行以下操作:

async def receive(self, text_data):
    text_data_json = json.loads(text_data)
    message = text_data_json['message']
    username = self.scope['user'].username
    profile_pic = self.scope['user'].profile.image.url  # None handling required
    room = text_data_json['room']

    await self.save_message(username, room, message)

    await self.channel_layer.group_send(
        self.room_group_name,
        {
            'type': 'chatroom_message',
            'message': message,
            'username': username,
            'profile_pic': profile_pic
        }
    )

async def chatroom_message(self, event):
    message = event['message']
    username = event['username']
    profile_pic = event['profile_pic']

    await self.send(text_data=json.dumps({
        'message': message,
        'username': username,
        'profile_pic': profile_pic
    }))

 # on the frontend
 chatSocket.onmessage = function (e) {
        const data = JSON.parse(e.data);
        console.log(data)
        if (data.message) {
                document.querySelector('#chat-text').innerHTML += (`<img id="imageid" src="${data.profile_pic}">` + data.username + '<br>' + data.message + '<br>');
            }
        else {
            
        }

Note that you can't make database calls from async context because database connector works in a synchronous manner.请注意,您不能从异步上下文进行数据库调用,因为数据库连接器以同步方式工作。 When you are getting a profile pic self.scope['user'].profile.image.url you are actually making a DB call to get user's profile.当您获得个人资料图片self.scope['user'].profile.image.url您实际上是在进行数据库调用以获取用户的个人资料。

What you need to do in such cases is make a db call using either database_sync_to_async or sync_to_async decorators.在这种情况下,您需要做的是使用database_sync_to_asyncsync_to_async装饰器进行database_sync_to_async调用。

For example:例如:

from channels.db import database_sync_to_async

@database_sync_to_async
def get_user_profile(self):
    return self.scope['user'].profile
 
# and in receive method you call it
async def receive(self, text_data):
    profile = await self.get_user_profile()
    profile_pic = profile.image.url
    ....

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Javascript-使用Facebook登录,成功登录后显示用户的个人资料图片 - Javascript - Login with Facebook, display user's profile picture after logged in successfully 发送消息后如何为用户添加角色 - How to add role to user after message is sent 上传后更新用户个人资料图片 - Update user profile picture after upload 使用ReactJS在Facebook身份验证之后获取用户的Facebook个人资料图片? - Getting the user's Facebook profile picture after Facebook authentication using ReactJS? 如何使用 javascript 在 Liferay 中检索用户资料图片 - How to retrieve a user profile picture in Liferay with javascript 如何使用 Keycloak 获取当前用户的个人资料图片? - How to get current user profile picture with Keycloak? 如何使用Javascript SDK V2.0获取Facebook用户朋友的头像 - How to get Facebook user's friends' profile picture using Javascript SDK V2.0 邮件成功发送后,在提交按钮中显示“已发送” - Display “Sent” in the submit button after the message got successfully sent Javascript-在Facebook上获得用户朋友的一张随机头像 - Javascript - get one random profile picture of user's friends on facebook 如何显示带有用户名和聊天消息的用户头像? - How to Display User Avatar With User's Name and Chat Message?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM