I'm trying to set up websockets to show any new entry in Post model (I'm new with websockets)
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
content = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
author = models.ForeignKey(
User,
related_name="blog_posts",
on_delete=models.CASCADE,
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
This is the consumers.py
class PostConsumer(ListModelMixin, GenericAsyncAPIConsumer):
queryset = Post.objects.all()
serializer_class = PostSerializer
permissions = (permissions.AllowAny,)
For checking if it works I have an html and I'm handling the websockets with vue.js
here's the more relevant part of the index.html
<title>Testing Websockets</title>
</head>
<body>
<div id="app" >
<div ></div>
<div >
<div >
<p >Display list of all the posts in Real-Time</p>
<div >
<table >
<thead >
<tr>
<th>Title</th>
<th>Status</th>
<th>Author</th>
</tr>
</thead>
<tbody>
<tr v-for="post in posts">
<td>
<p >[[ post.title ]]</p>
</td>
<td>
<span
:
>
[[ post.status ]]
</span>
</td>
<td>[[ post.author ]]</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.6.0.min.js"
integrity="sha256-/xUj 3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
crossorigin="anonymous"
></script>
<!-- JavaScript Bundle with Popper -->
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"
></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
vueApp = new Vue({
el: "#app",
delimiters: ["[[", "]]"],
data() {
return {
posts: [],
};
},
});
var ws = new WebSocket("ws://localhost:8001/ws/");
console.log(this.posts, "CHECKING WEBSOCKETS")
console.log(ws)
ws.onopen = function (e) {
ws.send(
JSON.stringify({
action: "list",
request_id: new Date().getTime(),
})
);
};
ws.onmessage = function (e) {
allData = JSON.parse(e.data);
if (allData.action === "list") {
vueApp.$data.posts = allData.data;
vueApp.$forceUpdate();
} else if (allData.action === "create") {
vueApp.$data.posts.push(allData.data);
}
};
</script>
</body>
</html>
async def connect(self, **kwargs):
await self.model_change.subscribe()
await super().connect()
@model_observer(Post)
async def model_change(self, message, observer=None, **kwargs):
await self.send_json(message)
@model_change.serializer
def model_serialize(self, instance, action, **kwargs):
return dict(data=PostSerializer(instance=instance).data, action=action.value)
when I run the in the console logs I see the following message
WebSocket connection to 'ws://localhost:8001/ws/' failed:
Please let me know if there's anything else that I need to share.
EDIT: I followed this youtube tutorial
CodePudding user response:
I had a tricky mistake. This is what I had in my settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'user',
'rest_framework_simplejwt',
'channels',
'daphne',
]
I moved channels and daphne to the top of the list and it worked. Like this
INSTALLED_APPS = [
'channels',
'daphne',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'user',
'rest_framework_simplejwt',
]