1. Django Tutorial(Airbnb) - Django Session & save_m2m
🌈 Django Session
🔥 Swich Btn for Session
🔥 Create Room in Host Mode
📌 이 포스팅에서는 Django의 Session으로 사용자의 모드(Guest/Host) 전환을 구현해보겠습니다.
모든 정보를 DB에 저장할 필요는 없습니다. Guest Mode나 Host Mode의 경우 Session을 사용하는게 더 간편합니다. Session은 Django의 Back단에서 정보를 잠시 유지하다가 Logout할 경우 모두 사라집니다. 따라서, 화폐정보(currency)처럼 일시적으로 필요한 정보들은 사실 Model에 field를 만들어 저장하는 것 보다 Session을 이용하는게 더 적절합니다.!
1. Swich Btn for Session
"users/views.py"에서 session을 활용해보도록 하겠습니다. 우선 session은 login된 상태여야하기 때문에 session에 올리거나 내릴 때 모두 login이 필수입니다. 따라서 "login_required" 데코레이션을 사용합니다.
- 🔎 from django.contrib.auth.decorators import login_required
Host 모드가 요청되면 "start_hosting" 함수가 호출되고, 다시 Guest 모드를 요청하면 "stop_hosting" 함수를 작동시킵니다.
# users/views.py from django.contrib.auth.decorators import login_required # 👈 "login_required" import ... ... @login_required def start_hosting(request): request.session["is_hosting"] = True # 👈 session에 "is_hosting" 추가 return redirect(reverse("core:home")) @login_required def stop_hosting(request): try: del request.session["is_hosting"] # 👈 session에서 "is_hosting" 제거 except KeyError: pass return redirect(reverse("core:home"))
위에 session 전환 기능을 하나의 함수로 기능하게 통합시킬 수 있습니다. 아래처럼 두 개의 경우밖에 없을 때에는 try 구문으로 전환시켜줄 수 있습니다. 즉, session에서 "is_hosting"를 제거하려고 시도하고, KeyError가 발생하면 session에 "is_hosting"이 없기 때문에 추가하는 것이죠. 이 방법은 사용하면, url 경로를 1개만 지정하면 된다는 장점이 있습니다!
from django.contrib.auth.decorators import login_required # 👈 "login_required" import ... ... @login_required def switch_hosting(request): try: del request.session["is_hosting"] # 👈 우선 제거를 시도하고, except KeyError: request.session["is_hosting"] = True # 👈 오류가 발생하면 추가 return redirect(reverse("core:home"))
- Url과 View는 아래처럼 매핑해주면됩니다. 마치 View의 함수를 toggle 기능처럼 작동시키는 것이죠!
from django.urls import path from . import views app_name = "users" urlpatterns = [ ... ... ... path("switch-hosting/", views.switch_hosting, name="switch-hosting"), # 👈 swaich-hosting ]
이제 View와 Url을 매핑하였으니, Template에서 사용자가 클릭한 버튼을 "partials/nav.html"에 생성하겠습니다. 버튼은 swich되기 때문에 session이 추가된 상태일 때는 Host 모드 상태이기 때문에 "Stop hosting" 버튼이 나타나야하고, 추가되지 않은 상태에서는 "Start hosting" 버튼이 나타나야 합니다.
이와 함께 Host 모드일 때는 객실을 생성할 수 있는 "Create Room" 버튼이 나타나도록 하겠습니다.
<ul class="flex items-center text-sm font-medium h-full"> {% if user.is_authenticated %} <li class="nav_link"> # 👈 session 전환 Btn <a href="{% url 'users:switch-hosting' %}"> {% if request.session.is_hosting %} # 👈 session에 "is_hosting"이 존재한다면,, Stop hosting {% else %} # 👈 session에 "is_hosting"이 존재하지 않는다면,, Start hosting {% endif %} </a> </li> {% if request.session.is_hosting %} # 👈 host mode일 때, "Create Room" bnt 노출 <li class="nav_link"><a href="#">Create Room</a></li> {% endif %} <li class="nav_link"><a href="{{user.get_absolute_url}}">Profile</a></li> <li class="nav_link"><a href="{% url "users:logout" %}">Log out</a></li> {% else %} <li class="nav_link"><a href="{% url "users:login" %}">Log in</a></li> <li class="nav_link"><a href="{% url "users:signup" %}">Sign up</a></li> {% endif %} </ul>
2. Create Room in Host Mode
1) Create Room
Host 모드일 때만 객실을 생성할 수 있는 버튼을 노출할 수 있게 했으니 이를 기능할 수 있게 처리해볼께요. CBV로 만들 때, save() 매서드를 가로채야할 때는 CreateView 보다 FormView 만드는 것이 좋습니다.
class CreateRoomView(user_mixins.LoggedInOnlyView, FormView): form_class = forms.CreateRoomForm # 👈 템플릿에 입력을 받기 위한 form입니다. template_name = "rooms/room_create.html" # 👈 객실을 생성하기 위해 render할 템플릿입니다.
"room/forms.py"의 "CreateRoomForm"은 ModelForm을 상속받아, 객실 생성을 위한 field를 지정해줍니다.
class CreateRoomForm(forms.ModelForm): class Meta: model = models.Room fields = ( "name", "description", "country", "city", "price", "address", "guests", "beds", "bedrooms", "baths", "check_in", "check_out", "instant_book", "room_type", "amenities", "facilities", "house_rule", )
"CreateRoomView"를 작동시킬 Url 경로를 매핑하겠습니다.
from django.urls import path from . import views app_name = "rooms" urlpatterns = [ path("create/", views.CreateRoomView.as_view(), name="create"), # 👈 CreateRoomView를 연결해줍니다. path("<int:pk>/", views.RoomDetail.as_view(), name="detail"), path("<int:pk>/edit/", views.EditRoomView.as_view(), name="edit"), path("<int:pk>/photos/", views.RoomPhotosView.as_view(), name="photos"), path("<int:pk>/photos/add", views.AddPhotoView.as_view(), name="add-photos"), path( "<int:room_pk>/photos/<int:photo_pk>/delete/", views.delete_photo, name="delete-photo", ), path( "<int:room_pk>/photos/<int:photo_pk>/edit/", views.EditPhotoView.as_view(), name="edit-photo", ), path("search/", views.SearchView.as_view(), name="search"), ]
- "Create Room" 버튼에 경로를 지정해줍니다.
<ul class="flex items-center text-sm font-medium h-full"> {% if user.is_authenticated %} <li class="nav_link"> <a href="{% url 'users:switch-hosting' %}"> {% if request.session.is_hosting %} Stop hosting {% else %} Start hosting {% endif %} </a> </li> {% if request.session.is_hosting %} # 👇 url을 연결해줄께요:) <li class="nav_link"><a href="{% url 'rooms:create' %}">Create Room</a></li> {% endif %} <li class="nav_link"><a href="{{user.get_absolute_url}}">Profile</a></li> <li class="nav_link"><a href="{% url "users:logout" %}">Log out</a></li> {% else %} <li class="nav_link"><a href="{% url "users:login" %}">Log in</a></li> <li class="nav_link"><a href="{% url "users:signup" %}">Sign up</a></li> {% endif %} </ul>
2) save_m2m()
이제 form에서 Room Object를 생성 후,, 저장하기 전 가로채서 생성된 Object를 View단으로 전달해보겠습니다.
class CreateRoomForm(forms.ModelForm): class Meta: model = models.Room fields = ( "name", "description", "country", "city", "price", "address", "guests", "beds", "bedrooms", "baths", "check_in", "check_out", "instant_book", "room_type", "amenities", "facilities", "house_rule", ) def save(self, *args, **kwargs): room = super().save(commit=False) # 👈 Object를 생성까지만 합니다. return room # 👈 그 Object를 View로 return합니다.
FBV에서는 is_valid()를 사용하지만, CBV에서는 form_vaild를 사용해 유효성 검사를 진행시킵니다. 유효하다면, save 매서드를 호출하여 "CreateRoomForm"에서 Object생성 후 저장하기 전 상태를 받아옵니다. 이후 현재 사용자를 host로 지정한 뒤, 저장시킵니다.
마지막으로 저장할 field들 중 Many-to-Mnay field가 있다면,, save_m2m 매서드를 이용해서 저장시킵니다.
class CreateRoomView(user_mixins.LoggedInOnlyView, FormView): form_class = forms.CreateRoomForm template_name = "rooms/room_create.html" def form_valid(self, form): room = form.save() # 👈 Form에서 생성된 Object 가져와요:) room.host = self.request.user # 👈 현재 사용자를 host로 지정합니다. room.save() # 👈 저장. form.save_m2m() # 👈 Many-to-Many 필드를 저장해줘요:) messages.success(self.request, "Room Uploaded") return redirect(reverse("rooms:detail", kwargs={"pk": room.pk})) # 👈 생성한 방으로 rediect
Author And Source
이 문제에 관하여(1. Django Tutorial(Airbnb) - Django Session & save_m2m), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jewon119/Django-기초-Django-Session저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)