투두리스트
룸 상세정보 보이기- 가입하기
댓글 기능
☝🏻 룸 상세페이지 <info>
- 공개방을 비번방으로 변경 가능 / 비번방을 공개방으로 변경 불가능
- 방장인 경우 왕관표시
- 댓글창 스크롤
1. view
#room/views.py
# 글 상세페이지
def room_info(request, pk):
room_pk = Room.objects.get(pk=pk)
res_data = { 'room': room_pk }
return render(request, 'room_info.html',res_data)
2. url
from django.urls import path
from . import views
urlpatterns = [
...
path('room/page/<int:pk>', views.room_info, name='room_info'), #글상세페이지
...
]
3. html
#room_info.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}{% endblock %}스ㅌㅓ디룸</title>
<link rel="stylesheet" href="/static/css/room_page.css">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://kit.fontawesome.com/5c2f488d06.js" crossorigin="anonymous"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
</head>
<body>
<!-- nav -->
<nav class="navbar navbar-expand-lg ">
<div class="container-fluid padding-none">
<div class="nav_left">
<a class="navbar-brand" href="/">스ㅌㅓ디룸</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
<div class="collapse navbar-collapse nav_right" id="navbarSupportedContent">
<!-- 검색창 -->
<form class="d-flex main_search_form" role="search" action="{% url 'search' %}" method="get">
<div class="form_btnbox">
<input class="form-control" type="search" placeholder="스터디 모집 찾기" aria-label="Search" name="q"
value="{{ q }}">
<button class="btn" type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor"
class="bi bi-search" viewBox="0 0 16 16">
<path
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z" />
</svg>
</button>
</div>
</form>
<!-- 로그인/로그아웃 했을 경우 유저의 현재 활동 가능 상태를 판단하는 제어문 -->
<ul class="navbar-nav nav-ul">
{% if request.user.is_authenticated %}
<li class="nav-item">
<a class="mypage">{{ request.user }}</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="/mypage/">마이페이지</a></li>
<li><a class="dropdown-item" href="/logout/">로그아웃</a></li>
</ul>
</li>
{% else %}
<li class="nav-item">
<a class="login" href="/login/">로그인</a>
</li>
<li class="nav-item">
<a class="resigter" href="/resigter/">회원가입</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
<!-- nav end -->
<div class="max-w-screen-2xl mx-auto p-5 sm:p-10 relative">
<div class="grid sm:grid-cols-2 gap-10 review_box">
<div class="bg-white shadow-lg border p-3 rounded-lg">
<div class="border-b mb-3 flex justify-between text-sm">
<div class="text-blue-600 flex items-center pb-2 pr-2 border-b-2 border-blue-600 uppercase">
<a href="#" class="font-semibold inline-block">info</a>
</div>
<!-- 수정/삭제 -->
{% if request.user == room.room_owner %}
<div class="setting_icon-modal">
<div class="modal_box">
<button type="button">
<a href="{% url 'room_edit' room.pk %}"
class="text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-full text-sm px-3 py-2.5 text-center mr-2 mb-2">수정</a>
</button>
<button type="button" class="" data-bs-toggle="modal"
data-bs-target="#exampleModal">
<a class="text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-full text-sm px-3 py-2.5 text-center mr-2 mb-2">삭제</a>
</button>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1"
aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-close" data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body">
스터디룸을 삭제하시겠습니까 ?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"
onclick="location.href = '/room/delete/{{ room.pk }}' ">예</button>
<button type="button" class="btn btn-primary"
onclick="location.href = '' ">아니오</button>
</div>
</div>
</div>
</div>
<!-- 가입하기-->
{% elif request.user != room.room_owner %}
<div>
<button type="button">
<a href=""
class="joinBtn text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-4 focus:outline-none focus:ring-cyan-300 dark:focus:ring-cyan-800 font-medium rounded-full text-sm px-3 py-2.5 text-center mr-2 mb-2">가입하기</a>
</button>
</div>
{% endif %}
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-5">
<div class="w-full">
<div class="mt-3 bg-white rounded-b lg:rounded-b-none lg:rounded-r flex flex-col justify-between leading-normal">
<div>
<!-- 공개방/비밀방 -->
{% if room.room_password %}
<div class="oner_box-secret">
<div class="oner_profile">
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-key-fill"
viewBox="0 0 16 16">
<path
d="M3.5 11.5a3.5 3.5 0 1 1 3.163-5H14L15.5 8 14 9.5l-1-1-1 1-1-1-1 1-1-1-1 1H6.663a3.5 3.5 0 0 1-3.163 2zM2.5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2z" />
</svg>
</div>
</div>
{% endif %}
<!-- 제목/부제목/내용 -->
<a class="text-gray-900 font-bold text-lg mb-2 hover:text-blue-600 transition duration-500 ease-in-out">
제목 : {{ room.title }}</a>
<p class="text-gray-700 text-xs mt-2">{{ room.sub_title }}</p>
<p class="text-gray-700 text-s mt-2">{{ room.content }}</p>
<p class="text-gray-700 text-xs mt-2">작성일 : {{ room.create | date:"Y-m-d" }}</p>
</div>
</div>
</div>
<!-- 가인한 멤버리스트 -->
<div class="lg:border-l lg:pl-4">
<div class="text-md border-b pb-2 mb-3">
<a href="#" class="text-gray-900 hover:text-blue-600 font-semibold">멤버 리스트</a>
</div>
<!-- 방장 -->
<div class="text-md border-b pb-2 mb-2">
<p class="text-gray-800 text-s plus-icon">방장 : {{ room.room_owner }}
<span><img src="/static/images/crown.png" alt=""></span>
</p>
</div>
<!-- 가입한 유저 -->
<div class="text-md border-b pb-2 mb-2">
<p class="text-gray-800 text-s">멤버 : 아직 없음</p>
</div>
<div class="text-md border-b pb-2 mb-2">
<p class="text-gray-800 text-s">멤버 : 아직 없음</p>
</div>
<div class="text-md border-b pb-2 mb-2">
<p class="text-gray-800 text-s">멤버 : 아직 없음</p>
</div>
</div>
<!-- 가입한 멤버리스트 끝 -->
</div>
</div>
<!-- 댓글창 -->
<div class="bg-white shadow-lg border p-3 rounded-lg review_scroll">
<div class="border-b mb-3 flex justify-between text-sm">
<div class="text-blue-600 flex items-center pb-2 pr-2 border-b-2 border-blue-600 uppercase">
<a class="font-semibold inline-block">댓글</a>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-1 gap-5">
<div class="w-full">
<div
class="mt-3 bg-white rounded-b lg:rounded-b-none lg:rounded-r flex flex-col justify-between leading-normal">
<ol class="relative border-gray-200 dark:border-gray-700">
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>아이디</p>
</div>
<p class="room_page-id ml-5">이런저런 내용 </p>
</li>
</ol>
<div class="line"></div>
<!-- 댓글 작성하기 -->
<div class=" room_page-li posi-fixed">
<form action="">
<div class="room_page-review">
<textarea placeholder="댓글을 입력해주세요."></textarea>
<button type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-send" viewBox="0 0 16 16">
<path
d="M15.854.146a.5.5 0 0 1 .11.54l-5.819 14.547a.75.75 0 0 1-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 0 1 .124-1.33L15.314.037a.5.5 0 0 1 .54.11ZM6.636 10.07l2.761 4.338L14.13 2.576 6.636 10.07Zm6.787-8.201L1.591 6.602l4.339 2.76 7.494-7.493Z">
</path>
</svg>
</button>
</div>
</form>
</div>
<!-- 댓글 작성끝 -->
</div>
</div>
</div>
</div>
<!-- 게시판 끝 -->
</div>
</div>
<script src="https://unpkg.com/flowbite@1.5.1/dist/flowbite.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js"
integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa"
crossorigin="anonymous"></script>
</body>
</html>
</body>
</html>
☝🏻 룸 상세페이지 <가입 리스트>
1. model
class Room_member(models.Model):
join_user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="가입자")
group = models.ForeignKey(Room, on_delete=models.CASCADE, verbose_name="room 정보")
date_joined = models.DateField(verbose_name="가입날짜")
def __str__(self):
return f'{self.group} {self.join_user} {self.date_joined}'
class Meta:
db_table = 'Room_member'
verbose_name = "room 유저리스트"
verbose_name_plural = "room 유저리스트"
2. view
☝🏻 룸 상세페이지 <댓글>
1. model
📌 on_delete 종류
1. CASCADE : ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField를 포함하는 모델 인스턴스(row)도 삭제된다.
2. PROTECT : ForeignKeyField가 바라보는 값이 삭제될 때 삭제가 되지않도록 ProtectedError를 발생시킨다.
3. SET_NULL : ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField값을 null로 바꾼다. (SET_DEFAULT)
4. SET_DEFAULT: ForeignKeyField가 바라보는 값이 삭제될 때 ForeignKeyField값을 지정된 default 값으로 바꾼다.
#room/models.py
class Room_comment(models.Model):
article = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE, verbose_name="room 정보")
comment = models.TextField(max_length=200, verbose_name="댓글 내용")
created_at = models.DateTimeField(default=timezone.now, verbose_name="작성일")
def __str__(self):
return f'{self.room} {self.comment}'
# return self.comment
class Meta:
db_table = 'Room_comment'
verbose_name = "room 댓글"
verbose_name_plural = "room 댓글"
2. view
comment = Room_comment.objects.filter(room=pk) -> 반환받은 룸의 pk즉 id값에 해당하는 roomdl라는 조건에 맞는 댓글 가져오기
#room/views.py
# 글 상세페이지
@login_required
def room_info(request, pk):
room_pk = Room.objects.get(pk=pk)
room_comment = Room_comment.objects.filter(room=pk)
res_data = { 'room': room_pk, 'room_comment': room_comment}
article = request.user #현재유저
# 댓글 생성
if request.method == 'POST':
comment = request.POST['comment'] #댓글 내용
commentobj = Room_comment()
commentobj.room = room_pk #방정보
commentobj.article = article #작성자
commentobj.comment = comment #댓글내용
commentobj.created_at = timezone.now() #현재시간
commentobj.save() #저장하기
return render(request, 'room_info.html', res_data)
3. html
#room_info.html
...
<!-- 댓글창 -->
<div class="bg-white shadow-lg border p-3 rounded-lg review_scroll">
<div class="border-b mb-3 flex justify-between text-sm">
<div class="text-blue-600 flex items-center pb-2 pr-2 border-b-2 border-blue-600 uppercase">
<a class="font-semibold inline-block">댓글</a>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-1 gap-5">
<div class="w-full">
<div
class="mt-3 bg-white rounded-b lg:rounded-b-none lg:rounded-r flex flex-col justify-between leading-normal">
<ol class="relative border-gray-200 dark:border-gray-700">
{% if not comment %} #댓글이 없을 경우
<p class="room_page-id ml-5">아직 댓글이 없습니다.</p>
{% endif %}
{% if comment %} #댓글이 있을 경우
{% for c in comment %}
<li class="mb-3 room_page-li">
<div class="room_page-title">
<img src="/static/images/profile.jpg" alt="">
<p>{{ c.article }}</p>
</div>
<p class="room_page-id ml-5">{{ c.comment }}</p>
<p class="room_page-id ml-5">{{ c.created_at }}</p>
</li>
{% endfor %}
{% endif %}
</ol>
<div class="line"></div>
<!-- 댓글 작성하기 -->
<div class=" room_page-li posi-fixed">
<form method="post">
{% csrf_token %}
<div class="room_page-review">
<textarea placeholder="댓글을 입력해주세요."></textarea>
<button type="submit">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"
fill="currentColor" class="bi bi-send" viewBox="0 0 16 16">
<path
d="M15.854.146a.5.5 0 0 1 .11.54l-5.819 14.547a.75.75 0 0 1-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 0 1 .124-1.33L15.314.037a.5.5 0 0 1 .54.11ZM6.636 10.07l2.761 4.338L14.13 2.576 6.636 10.07Zm6.787-8.201L1.591 6.602l4.339 2.76 7.494-7.493Z">
</path>
</svg>
</button>
</div>
</form>
</div>
<!-- 댓글 작성끝 -->
</div>
</div>
</div>
</div>
<!-- 댓글창 끝 -->
...
'FrameWork > Django' 카테고리의 다른 글
AWS EC2, Ubuntu에서 Django 프로젝트 배포하기 - 1) 인스턴스 생성 , 우분투 접속, anaconda 설치 (1) | 2023.05.22 |
---|---|
룸 생성페이지 / 수정페이지 (0) | 2022.10.05 |
마이페이지 (1) | 2022.09.23 |
9월 15일 (목) 질문 (0) | 2022.09.16 |
9월 14일 (수) 룸 가입하기 (0) | 2022.09.15 |