Django - How can my asgi websocket path be on my swagger - django

I am creating an api where two endpoints are using the ws(s) protocol.
As my API is behind Google endpoint, Every endpoint needs to be defined onto an OpenApi2.0 file.
To create this definition I use drf-yasg.
I have a routing. py file like this:
""" systems/routing.py"""
from django.urls import path
from .consumers.list_sessions_consumer import MyFirstConsumer
from .consumers.session_consumer import MySecondConsumer
urlpatterns = [
path(r'v1/ws/yo/<str:uuid>/sessions-sumpup', MyFirstConsumer.as_asgi()),
path(r'v1/ws/yo/<str:uuid>/sessions', MySecondConsumer.as_asgi()),
]
and I register it onto my asgi.py file like this:
# pylint: skip-file
""" main/asgi.py """
import os
import django
from django.core.asgi import get_asgi_application
django_asgi_app = get_asgi_application()
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'main.settings')
django.setup()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from systems.websockets.routing import urlpatterns as system_websocket_url
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": AuthMiddlewareStack(
URLRouter(
system_websocket_url
)
),
})
Don't mind the import order this is due to this error: Django apps aren't loaded yet when using asgi
So my socket works as expected, now, I want my command line: python3 manage.py generate_swagger swagger.yaml to add these new endpoint to my swagger file.
I tried to directly add my url to the same object then all my other urls like so:
urlpatterns = [
path(r'v1/toto/<str:uuid>', MyView.as_view()),
...,
path(r'v1/ws/yo/<str:uuid>/sessions-sumpup', MyFirstConsumer.as_asgi()),
path(r'v1/ws/yo/<str:uuid>/sessions', MySecondConsumer.as_asgi()),
]
But nothing shows up in my swagger file.
Any ideas ?
Thanks

Related

How to remove last / character in root URL API in Django

API only work with url below:
http://127.0.0.1:1997/api/v1/groups/
How can I remove the last '/' so that it works like below:
http://127.0.0.1:1997/api/v1/groups
My config url code:
import os
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from rest_framework.schemas import get_schema_view
from rest_framework_swagger.renderers import SwaggerUIRenderer, OpenAPIRenderer
from groups import views as group_views
API_VERSION = os.getenv('API_VERSION')
API_ROOT = f"api/{API_VERSION}/"
router = routers.DefaultRouter()
router.register('groups', group_views.GroupViewSet)
schema_view = get_schema_view(
title='next_blog',
renderer_classes=[OpenAPIRenderer, SwaggerUIRenderer])
urlpatterns = [
path('admin', admin.site.urls),
path('api_auth', include(
'rest_framework.urls', namespace='rest_framework')),
path('docs', schema_view, name='docs'),
path(API_ROOT, include(router.urls)),
]
Thanks everyone !
Set the trailing_slash argument to False when instantiating the router.
router = DefaultRouter(trailing_slash=False)
Django Rest Framework Default Router

Importing from views directory

In my project I have an app called api where I keep my viewsets in a directory called views. I keep getting ModuleNotFoundError: No module named 'api.views.book'; 'api.views' is not a package where I import in my api/urls.py
api/urls.py
from rest_framework import routers
from api.views.book import BookViewset
router = routers.DefaultRouter()
router.register(r'books', BookViewset, 'books')
api_urls = router.urls
In my main urls.py I'm doing this:
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from api.urls import api_urls
urlpatterns = [
path('api', include(api_urls)),
path('admin/', admin.site.urls),
]
I didn't get an error until I imported api_urls
I should mention that api is included in INSTALLED_APPS
You need to include a file named __init__.py in a directory to make it a package, then you can import from it
In your case you need a file api/views/__init__.py

"Cannot import ASGI_APPLICATION module %r" % path channels problem

I got this error: ImproperlyConfigured("Cannot import ASGI_APPLICATION module %r" % path)
Here is my routing.py:
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from channels.auth import AuthMiddlewareStack
from django.urls import path
from messanger.contacts.consumers import ChatConsumer
application = ProtocolTypeRouter({
# Empty for now (http->django views is added by default)
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
[
path('user-notification', ChatConsumer)
]
)
)
)
})
When i remove this line of code, runserver work: from messanger.contacts.consumers import ChatConsumer
But i don't understand what's wrong with my consumers file in contacts app:
from channels.consumer import AsyncConsumer
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
await self.send({
"type": "websocket.accept",
})
async def websocket_receive(self, event):
await self.send({
"type": "websocket.send",
"text": event["text"],
})
In your settings.py file add:
ASGI_APPLICATION = 'yourappname.asgi.application'
I was able to solve this issue by going in the asgi.py file and import get_asgi_application() which act as tradition http request fallback Like so in asgi.py :
mport os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
from django.urls import path
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
# Initialize Django ASGI application early to ensure the AppRegistry
# is populated before importing code that may import ORM models.
django_asgi_app = get_asgi_application()
from chat.consumers import AdminChatConsumer, PublicChatConsumer
application = ProtocolTypeRouter({
# Django's ASGI application to handle traditional HTTP requests
"http": django_asgi_app,
# WebSocket chat handler
"websocket": AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter([
path("chat/admin/", AdminChatConsumer.as_asgi()),
path("chat/", PublicChatConsumer.as_asgi()),
])
)
),
})
You need to add in your settings.py file :
ASGI_APPLICATION = 'yourappname.routing.application'
and that is because ASGI_APPLICATION is looking for application = ... in your files. And also there could be a potentional problem with your not adding ChatConsumer.as_asgi() in your path which will instantiate a new consumer instance for each connection.

Django daphne asgi: Django can only handle ASGI/HTTP connections, not websocket

This is really frustrating, I did set everything up according to the documentation, but daphne keeps throwing an error when I try to run it independently, it does work correctly when I use python manage.py run server. this is very frustrating and I can't seem to find similar error anywhere else
2020-01-25 09:57:17,627 INFO Starting server at tcp:port=8000:interface=127.0.0.1
2020-01-25 09:57:17,628 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2020-01-25 09:57:17,628 INFO Configuring endpoint tcp:port=8000:interface=127.0.0.1
2020-01-25 09:57:17,629 INFO Listening on TCP address 127.0.0.1:8000
127.0.0.1:44516 - - [25/Jan/2020:09:57:27] "WSCONNECTING /ws/score/" - -
2020-01-25 09:57:28,637 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
File "/home/sofdeath/.local/lib/python3.7/site-packages/daphne/cli.py", line 30, in asgi
await self.app(scope, receive, send)
File "/home/sofdeath/.local/lib/python3.7/site-packages/django/core/handlers/asgi.py", line 146, in __call__
% scope['type']
Django can only handle ASGI/HTTP connections, not websocket.
127.0.0.1:44516 - - [25/Jan/2020:09:57:28] "WSDISCONNECT /ws/score/" - -
^C2020-01-25 09:57:39,126 INFO Killed 0 pending application instances
here is my asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tabulator.settings')
application = get_asgi_application()
my routing.py:
from django.urls import re_path
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
import judge.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
judge.routing.websocket_urlpatterns
)
)
),
})
and in my settings.py:
INSTALLED_APPS = [
...
'channels',
]
...
WSGI_APPLICATION = 'tabulator.wsgi.application'
ASGI_APPLICATION = "tabulator.routing.application"
...
CHANNEL_LAYERS = {
"default": {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
change your asgi.py to this:
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tabulator.settings')
django.setup()
application = get_default_application()
You need to change your asgi.py according to this
# mysite/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
change your asgi.py as #ahmad says and edit your settings.py to this:
CHANNEL_LAYERS = {
"default": {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [("redis", 6379)],
},
},
}
and be sure that DEBUG = False. That is because you are not running your project on local server it it will throw an error if you use "127.0.0.1" or "localhost".

How to fix ImportError: No module named urls

i have installed django 1.10. And then ckeditor 5.0.3
When done with config i got an error "ImportError: No module named urls"
There is config settings.py:
INSTALLED_APPS = [
...
'ckeditor',
]
CKEDITOR_UPLOAD_PATH = 'upload/'
There is urls.py:
from django.conf.urls import url, include
(r'^ckeditor/', include('ckeditor.urls')),
There is urls.py of ckeditor_uploader:
from __future__ import absolute_import
import django
from django.conf.urls import url
from django.contrib.admin.views.decorators import staff_member_required
from django.views.decorators.cache import never_cache
from . import views
if django.VERSION >= (1, 8):
urlpatterns = [
url(r'^upload/',
staff_member_required(views.upload),
name='ckeditor_upload'),
url(r'^browse/', never_cache(staff_member_required(views.browse)),
name='ckeditor_browse'),
]
else:
from django.conf.urls import patterns
urlpatterns = patterns(
'',
url(r'^upload/', staff_member_required(views.upload),
name='ckeditor_upload'),
url(r'^browse/', never_cache(staff_member_required(views.browse)),
name='ckeditor_browse'),
)
Please any help!
WSGI_APPLICATION:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "blago.settings")
application = get_wsgi_application()
Read the documentation
NOTICE: django-ckeditor 5 has backward incompatible code moves against 4.5.1.
File upload support have been moved to ckeditor_uploader. The urls are in ckeditor_uploader.urls while for file uploading widget you have to use RichTextUploadingField instead of RichTextField.
..
Add ckeditor_uploader to your INSTALLED_APPS setting.
...
Add CKEditor URL include to your project's urls.py file:
(r'^ckeditor/', include('ckeditor_uploader.urls')),