304번째 줄: |
304번째 줄: |
| </syntaxhighlight> | | </syntaxhighlight> |
| |} | | |} |
| + | == 개요 == |
| + | 레디스 서버를 이용한 실시간 채팅 구현 |
| + | ===사전설정=== |
| + | {| class="wikitable" |
| + | !과정 |
| + | !설명 |
| + | !방법 |
| + | |- |
| + | | 서버 설치 |
| + | | |
| + | |apt-get install redis-server |
| + | |- |
| + | |서버 테스트 |
| + | |서버가 잘 설치되었는지 테스트. |
| + | 서버 구동에 대한 메시지가 뜬다. |
| + | |redis-server |
| + | |- |
| + | |채널 라이브러리 설치 |
| + | |장고에서 사용할 채널 라이브러리를 설치한다. |
| + | |pip install -U channels |
| + | |- |
| + | |연동 라이브러리 설치 |
| + | |서버와 채널을 연동할 라이브러리를 설치한다. |
| + | |pip install channels_redis |
| + | |- |
| + | |앱을 만든다. |
| + | | |
| + | |django-admin startapp chat |
| + | |- |
| + | |앱 등록 |
| + | |settings.py에 추가. |
| + | |INSTALLED_APPS 가장 위에 'channels', 'chat'을 맨 위에 추가해준다. |
| + | 다른 서드파티 앱과 충돌할 수 있어 가장 처음에 둔다. |
| + | |- |
| + | |세팅 |
| + | |settings.py 안에 추가. |
| + | |<syntaxhighlight lang="python"> |
| + | ASGI_APPLICATION = 'config.routhing.application' |
| + | |
| + | CHANNEL_LAYERS = { |
| + | 'default':{ |
| + | 'BACKEND': 'channels_redis.core.RedisChannelLayer', |
| + | 'CONFIG': { |
| + | "hosts": [('127.0.0.1', 6379)], |
| + | } |
| + | } |
| + | } |
| + | |
| + | os.environ["DJANGO_ALLOW_ASYNC_UNDAFE"] = "true" |
| + | </syntaxhighlight>을 추가해준다.(대강 스테틱 설정 아래면 적당) |
| + | |} |
| + | ==모델작성== |
| + | chat 앱의 models.py 작성<syntaxhighlight lang="python"> |
| + | from django.db import models |
| + | from django.conf import settings |
| + | |
| + | class Room(models.Model): |
| + | room_name = models.CharField(max_length=100, blank=True) |
| + | users = models.ManyToManyfield( |
| + | settings.AUTH_USER_MODEL, # 유저모델과 연결한다. |
| + | blank=True, |
| + | related_name = 'rooms') # 룸이라는 인덱스 지정. |
| + | |
| + | def __str__(self): |
| + | return self.room_name |
| + | |
| + | class Message(models.Model): |
| + | user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=1) |
| + | room = models.ForeignKey(Room, related_name='messages', default=1, on_delete=models.CASCADE) |
| + | content = models.TextField(blank=True) |
| + | created_at = models.DateTimeField(auto_now_add=True) |
| + | |
| + | def __str__(self): |
| + | return self.content |
| + | </syntaxhighlight>chat앱의 admin.py 작성<syntaxhighlight lang="python"> |
| + | from django.contrib import admin |
| + | from .models import Room, Message |
| + | |
| + | @admin.register(Room) |
| + | class RoomAdmin(admin.ModelAdmin): |
| + | list_display = ['id', 'room_name'] |
| + | list_display_links = ['room_name'] |
| + | |
| + | @admin.register(Room) |
| + | class MessageAdmin(admin.ModelAdmin): |
| + | list_display = ['user', 'room', 'content', 'created_at'] |
| + | list_display_links = ['user', 'room', 'content', 'created_at'] |
| + | </syntaxhighlight>대화모델 작성(보통 친구모델 등에 작성된다.)(근데 그냥 chat 앱 안에 작성하면 안되나...?)<syntaxhighlight lang="python"> |
| + | ... |
| + | from .chat.models import Room, Message |
| + | |
| + | class chat_connection(models.Model): |
| + | target = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, on_delete=models.CASCADE) # 상대방 |
| + | room = models.ForeignKey(Room, blank=True, on_delete=models.SET_NULL, null=True) # null옵션이 있어야 하나..? 없어도 될듯, 강의에선 친구모델 위에 더하느라 붙인듯. |
| + | user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, on_delete=models.CASCADE) # 나 |
| + | created_at = models.DateField(auto_now_add=True) |
| + | |
| + | def __str__(self): |
| + | return self.user.username + "채팅" # 사용자명을 반환한다. |
| + | </syntaxhighlight> |
| + | ==뷰 작성== |
| + | <syntaxhighlight lang="python"> |
| + | from django.shortcuts import render, get_object_or_404 |
| + | forom django.contrib.auth import get_user_model |
| + | from chat.models import * |
| + | import logging |
| + | |
| + | def start_chat(request): |
| + | from_user = # 본인의 유저모델 가져오기 |
| + | to_user = 유저모델.objects.get(pk=target_request_id) # 상대의 유저모델 가져오기(이름이나 pk로 불러오게 하면 될듯) |
| + | |
| + | room_name = "{},{}".format(from_user.username, to_user.username) |
| + | room = Room.objects.create(room_name=room_name) # 룸을 만든다. |
| + | |
| + | def chat_list(request): |
| + | user = request.user |
| + | user_profile = user.user_profile |
| + | friends = user.friends.all() # 모든 친구 불러오기...(채팅자 목록이라고 보면 됨.) |
| + | |
| + | context = {'user_profile': user_profile, |
| + | 'friends':friends, |
| + | } |
| + | |
| + | return render(request, 'chat/chat_list.html', context) |
| + | |
| + | def room(request, room_id): |
| + | user = request.user |
| + | user_profile = user.profile |
| + | friends = user.friends.all() # 모든 친구 불러오기...(채팅자 목록이라고 보면 됨.) |
| + | |
| + | room = Room.objects.get(pk=room_id) # 룸 모델에서 해당 pk에 맞는 룸 불러오기 |
| + | friends_uer = room.users.all().exclude(pk=user.id).first() |
| + | |
| + | context = {'current_user': user, |
| + | 'user_profile': user_profile, |
| + | 'friends':friends, |
| + | 'room':room, |
| + | 'friends_user': friends_user, |
| + | } |
| + | |
| + | return render(request, 'chat/room.html', context) |
| + | |
| + | |
| + | </syntaxhighlight> |
| + | ==url 작성== |
| + | config의 url을 넘김 처리하고.. |
| + | |
| + | chat앱 안의 urls.py를 작성한다.<syntaxhighlight lang="python"> |
| + | from .views import * |
| + | |
| + | app_name= 'chat' |
| + | |
| + | urlpatterns = [ |
| + | path('', chat_list, name='chat_list'), |
| + | paht('<str:room_id', room, name='room'), |
| + | ] |
| + | </syntaxhighlight> |
| + | ==탬플릿 작성 == |
| + | chat 앱 안의 templates 폴더를 만든 다음 넣는다.<syntaxhighlight lang="html+django"> |
| + | <!--확장코드--> |
| + | |
| + | <!--들어가야 할 것들--> |
| + | <script src="{% static 'js/messenger.js' %}"></script> |
| + | |
| + | <div id="user_list"> |
| + | {% for friend in friends %} |
| + | {% if friend.room %} |
| + | <li name="{{ friend.room.id }}"><a href="/chat/{{ friend.room.id }}/" |
| + | <div>{{ friend.user }}</div> |
| + | </div> |
| + | |
| + | <div id="time_line"> |
| + | <div id="main_section"> |
| + | <div id="feed"> |
| + | <div id="text_field"> |
| + | <input type="text" id="txt"> |
| + | <button type="submit" id="btn">전송</button> |
| + | </div> |
| + | </div> |
| + | </div> |
| + | </div> |
| + | </syntaxhighlight> |
| [[분류:장고 기능구현(중급)]] | | [[분류:장고 기능구현(중급)]] |