Home > Enterprise >  djangorestframework does not work when django channel is applied :((
djangorestframework does not work when django channel is applied :((

Time:09-18

I am developing a chatting app that allows social login. While developing all restapi functions, including social login functions, and developing chat customers using channel libraries, there was a problem with social login. This code is chatcustomer using websocketcunsumer.

enter code hereimport json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from .models import *
class ChatConsumer(WebsocketConsumer):
def connect(self):
    self.room_name = self.scope['url_route']['kwargs']['room_name']
    self.room_group_name = 'chat_%s' % self.room_name
    # Join room group
    async_to_sync(self.channel_layer.group_add)(
        self.room_group_name,
        self.channel_name
    )
    self.accept()

def disconnect(self, close_code):
    # Leave room group
    async_to_sync(self.channel_layer.group_discard)(
        self.room_group_name,
        self.channel_name
....

this is setting for channel

INSTALLED_APPS = [
 'channels',
]
ASGI_APPLICATION = 'project.routing.application'

CHANNEL_LAYERS = {
"default": {
     "BACKEND": "channels.layers.InMemoryChannelLayer"
  }
} 

routing.py in project root

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import chat.routing


application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

asgi.py

import os
import django

from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
django.setup()
application = get_default_application()

routing.py in chatapp

from django.urls import re_path

from . import consumers
websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w )/$', consumers.ChatConsumer.as_asgi()),
]

this is social login views.py

@api_view(['POST'])    
def authenticate_kakao(request):

    access_token = request.data["access_token"]
    code =request.data['code']
    """
    Email Request
    """
    print("process1")
    profile_request = requests.get(
        "https://kapi.kakao.com/v2/user/me", headers={"Authorization": f"Bearer {access_token}"})
    print("process2")
    profile_json = profile_request.json()
    kakao_account = profile_json.get('kakao_account')

    email = kakao_account.get('email')
    profile = kakao_account.get("profile")
    nickname = profile.get("nickname")
    profile_image = profile.get("profile_image_url") 
    print("process3")
    """
    Signup or Signin Request
    """
    try:
        user = User.objects.get(email=email)
        social_user = SocialAccount.objects.get(user=user)
        if social_user is None:
            return Response({'err_msg': 'email exists but not social user'}, status=status.HTTP_400_BAD_REQUEST)
        if social_user.provider != 'kakao':
            return Response({'err_msg': 'no matching social type'}, status=status.HTTP_400_BAD_REQUEST)
        data = {'access_token': access_token, 'code': code}    
        accept = requests.post("http://localhost:8000/accounts/kakao/login/allauth/", data=data)
        print("process5")
        accept_status = accept.status_code
        if accept_status != 200:
            return Response({'err_msg': 'failed to signin'}, status=accept_status)
        accept_json = accept.json()
        #User model update
        print("process6")
        return Response(accept_json)
    except User.DoesNotExist:
        data = {'access_token': access_token, 'code': code}
        accept = requests.post(
            "http://localhost:8000/accounts/kakao/login/allauth/", data=data)
        
        print("process7")
        accept_status = accept.status_code
        if accept_status != 200:
            return Response({'err_msg': 'failed to signup'}, status=accept_status)
        print("process8")
        accept_json = accept.json()
        #User model update
        print("process9")
        return Response(accept_json)

class KakaoLogin(SocialLoginView):
    adapter_class = kakao_view.KakaoOAuth2Adapter
    client_class = OAuth2Client

and urls.py

urlpatterns = [
    path('kakao/authenticate/', login.authenticate_kakao),
    path('kakao/login/allauth/', login.KakaoLogin.as_view()),
]

this is server log

$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
September 17, 2022 - 15:15:17
Django version 4.0.6, using settings 'project.settings.local'
Starting ASGI/Channels version 3.0.5 development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Forbidden: /dj-rest-auth/user/
HTTP GET /dj-rest-auth/user/ 403 [0.02, 127.0.0.1:49400]
process1
process2
process3
process4

there is a point that sends a request to 'kakao/login/allauth' inside of the function 'kakao/authenticate', and this is where the server stops. It seems strange to you, but it worked well until I applied the channel.

In my opinion, it became impossible for the server to process various requests by applying channel. but why? i don't understand this reason plz help me

CodePudding user response:

I think you are missing a few cases. I will give you a clear way of configuring WebSocket and HTTP apps. settings.py:

INSTALLED_APPS = [
    'channels',
    'rest_framework'
    # and your other apps here
]
ROOT_URLCONF = 'project.urls'

WSGI_APPLICATION = 'project.wsgi.application'
ASGI_APPLICATION = "project.asgi.application"

CHANNEL_LAYERS = {
"default": {
     "BACKEND": "channels.layers.InMemoryChannelLayer"
  }
} 

asgi.py:

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
import django

django.setup()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.security.websocket import AllowedHostsOriginValidator
import chat.routing

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AllowedHostsOriginValidator(AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    )),
})

chat/routing.py

from django.urls import re_path

from . import consumers
websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w )/$', consumers.ChatConsumer.as_asgi()),
]

install uvicorn to run asgi application:

pip install uvicorn[standard]

run server command:

uvicorn project.asgi:application --reload

and it will work as expected.

  • Related