๐ Profile Page
๐ฅ Setting Profile
๐ฅ Read Profile
๐ฅ UpdateView ์ฌ์ฉํ๊ธฐ
1. Setting Profile
1) Absolute URL
- nav.html์ ํ๋กํ ํ์ด์ง๋ก ์ด๋ํ ์ ์๋ ๋งํฌ๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
<ul class="flex items-center text-sm font-medium h-full">
{% if user.is_authenticated %}
<li class="nav_link"><a href="{% url "users:profile" %}">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>
- profile ๋งํฌ๋ฅผ ํด๋ฆญํ์์ ๋, ์คํ๋ ๋ก์ง์ "DetailView"๋ฅผ ์์๋ฐ์ CBV("UserProfileView")๋ก ๋ง๋ค์ด ์ค๋๋ค.
from django.views.generic import DetailView
...
...
...
class UserProfileView(DetailView):
pass
- ํ๋กํ ํ์ด์ง๋ฅผ ์์ฒญํ์์ ๋, ์ ๊ทผํ ๊ฒฝ๋ก("users:profile")์ View์ CBV("UserProfileView") ๋งคํํด์ค๋๋ค.
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [
...
...
path("<int:pk>/", views.UserProfileView.as_view(), name="profile"),
]
- ์๋ฌ๊ฐ ๋ฐ์ํ ์ด์ ๋ urls.py์์๋ <int:pk>๋ก ์ธ์๋ฅผ ์์ฒญํ๊ณ ์๋๋ฐ, Templates์์ญ์์ pk๊ฐ์ ์ ๋ฌํด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์
๋๋ค. ์๋์ฒ๋ผ "user.pk"๋ฅผ ๋ฃ์ด ํด๊ฒฐํ ์๋ ์์ง๋ง, "get_absolute_url"์ ์ฌ์ฉํด๋ณด๊ฒ ์ต๋๋ค.
- ๐
<li class="nav_link"><a href="{% url "users:profile" user.pk %}">Profile</a></li>
- Django์ Model๋ค์ "get_absolute_url"์ด๋ผ๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค. users/models.py์ "get_absolute_url"์ ๋ฉ์๋๋ฅผ ์์ฑํด url๊ณผ ์ ๋ฌํ ์ธ์๋ฅผ ์ง์ ํด์ค๋๋ค. "get_absolute_url" ๋งค์๋๋ฅผ ์ด์ฉํ๋ฉด Admin Panel์์ "View ON SITE" ๊ธฐ๋ฅ ์๋์ผ๋ก ์ ๊ณต๋ฐ์ ์ ์์ต๋๋ค.
from django.shortcuts import reverse
...
...
def get_absolute_url(self):
return reverse("users:profile", kwargs={"pk": self.pk})
- nav.html์ profile ๋งํฌ๋ก ์ ๊ทผํ์์ ๋, models์ "get_absolute_url" ๋งค์๋๊ฐ ์๋ํ ์ ์๋๋ก ์ฐ๊ฒฐํด ์ค๋๋ค.
<ul class="flex items-center text-sm font-medium h-full">
{% if user.is_authenticated %}
<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. Read Profile
1) context_object_name
- ํ๋กํ ํ์ด์ง ๋งํฌ๋ฅผ ํด๋ฆญํ๋ฉด, ํ์ฌ ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ pk๊ฐ์ url์์ ์ป์ ๊ฒ์ ๋ณผ ์ ์์ด์.
- ์ ์ค๋ฅ๋ ์ด๋ View์์ ์ด๋ค ๋ชจ๋ธ์ธ์ง ์ง์ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐ์ํ์์ด์. ์ด์ ๋ชจ๋ธ์ ์ง์ ํฉ๋๋ค.
- context_object_name์ View์์ Template์ ์ ๋ฌํ๋ "Context"์ ์ด๋ฆ์ ์ง์ ํ๋ ๊ธฐ๋ฅ์ ํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ก๊ทธ์ธํ๋ ์ฌ์ฉ์ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฅดํฌ ์ ์๋๋ก ์ง์ ํด ํด์ค๋๋ค:)
from django.views.generic import DetailView
...
...
...
class UserProfileView(DetailView):
model = models.User
context_object_name = "user_obj"
- model์ ์ค์ ํ๊ณ ์๋ก๊ณ ์นจ์ ํ๋ฉด, Django๊ฐ Template(user_detail.html)๋ฅผ ์ฐพ๊ณ ์๋ค์. ์ฌ์ฉ์์ Profile์ ๋ณด์ฌ์ค Template๋ฅผ ๋ง๋ค์ด ์ค๊ป์:)
- ์ด์ user_obj๋ฅผ ํ
ํ๋ฆฟ ๋ณ์๋ฅผ ์ด์ฉํ์ฌ Model์ ํ๋์ ์ ๊ทผํ ์ ์๊ณ , ์ด์ ํ๋กํ ํ์ด์ง๋ฅผ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
{% extends "base.html" %}
{% block page_title %}
Profile
{% endblock page_title %}
{% block content %}
<div class="container lg:w-5/12 md:w-1/2 xl:w-1/4 mx-auto my-10 flex flex-col items-center border p-6 border-gray-400">
{{user_obj.first_name}}
</div>
{% endblock content %}
3) Profile Page ๊ตฌ์ฑ
- "user"์ "user_obj"๊ฐ ์ผ์นํ ๋๋ง, edit ๋ฒํผ์ด ๋ณด์ด๋๋ก ์ฒ๋ฆฌํ๊ณ , ํ๋กํ ์๋์ชฝ์ ๋ก๊ทธ์ธํ ์ฌ์ฉ์๊ฐ host์ธ ๊ฐ์ค ์ ๋ณด๊ฐ ํ์์ด์. ๋ํ avatar๋ฅผ ํ์ํ๋ ํ
ํ๋ฆฟ์ includeํ์ฌ ์ฌ์ฉํ์๊ณ , include template์ชฝ์ผ๋ก ํ
ํ๋ฆฟ ๋ณ์๋ฅผ ์ ๋ฌํ๊ณ ์ํ๋ฉด with์ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
- ๐ {% include "mixins/user_avatar.html" with user=user_obj %}
# user_detail.html
{% extends "base.html" %}
{% block page_title %}
{{user_obj.first_name}}'s Profile
{% endblock page_title %}
{% block content %}
<div class="h-75vh">
<div class="container lg:w-5/12 md:w-1/2 xl:w-1/4 mx-auto my-10 flex flex-col items-center border p-6 border-gray-400 ove">
{% include "mixins/user_avatar.html" with user=user_obj %}
<div class="flex items-center">
<span class="text-3xl mt-1">{{user_obj.first_name}}</span>
{% if user_obj.superhost %}
<i class="fas fa-check-circle text-teal-400 ml-1"></i>
{% endif %}
</div>
<span class="text-lg mb-5">{{user.bio}}</span>
{% if user == user_obj %}
<a href="#" class="btn-link">Edit Profile</a>
{% endif %}
</div>
{% if user_obj.rooms.count > 0 %}
<div class="container mx-auto pb-10 flex flex-col items-center">
<h3 class="mb-12 text-2xl">{{user_obj.first_name}}'s Rooms</h3>
<div class="flex flex-wrap -mx-40 mb-10">
{% for room in user_obj.rooms.all %}
{% include 'mixins/room_card.html' with room=room %}
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock content %}
- avatar์ฒ๋ผ ์ฌ๊ธฐ์ ๊ธฐ์ ์์ฃผ ์ฌ์ฉ๋๋ ํจํด์ ๊ฐ์ง ๊ฒฝ์ฐ, ๋ณ๋์ html๋ก ๋ถ๋ฆฌํ ๋ค ์ฌ๋ฌ ๊ณณ์์ inlcudeํ์ฌ ์ฌ์ฉํ๋ฉด template๋ค์ ๋ณด๋ค ๊ฐ๊ฒฐํ๊ฒ ๊ตฌ์ฑํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ avatar๊ฐ ์กด์ฌํ๋ค๋ฉด ์ด๋ฏธ์ง๋ฅผ ๋ํ๋ด๊ณ , ์ด๋ฏธ์ง๊ฐ ์๋ค๋ฉด ์ด๋ฆ์ ์ฒซ๋ฒ์งธ ๋ฌธ์๋ฅผ ๋ํ๋๊ฒ ํ์์ด์. ์ด๋ฅผ ์ํด "|first" ํ
ํ๋ฆฟ ํํฐ๋ฅผ ์ฌ์ฉํ์์ต๋๋ค.
- ๐ {{user.first_name|first}}
{% if user.avatar %}
<div class="h-20 w-20 rounded-full bg-cover" style="background-image: url({{user.avatar.url}});">
{% else %}
<div class="h-20 w-20 bg-gray-700 rounded-full text-white flex justify-center items-center overflow-hidden">
<span class="text-3xl">{{user.first_name|first}}</span>
{% endif %}
</div>
3. UpdateView ์ฌ์ฉํ๊ธฐ
1) UpdateView
- Profile์ ์์ ํ ์ ์๋ ๊ธฐ๋ฅ์ ์ํด UpdateView๋ฅผ ์์ ๋ฐ์ CBV("UpdateProfileView")๋ฅผ ๊ฐ๋จํ ๋ง๋ค ์์ฑํ์์ด์.
import os
import requests
from django.views.generic import FormView, DetailView, UpdateView
from django.urls import reverse_lazy
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login, logout
from django.core.files.base import ContentFile
from django.contrib import messages
from . import forms, models
...
...
...
class UpdateProfileView(UpdateView):
pass
- users/urls.py์ "UpdateProfileView"๋ฅผ ๋งคํํด์ค๊ป์:)
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [
...
...
path("update-profile/", views.UpdateProfileView.as_view(), name="update"),
]
2) get_object()
- UpdateView์์ "get_object()"๋งค์๋๋ฅผ ํตํด ์์ ํ Object๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ด์.
- "template_name"์ ํตํด Django๊ฐ renderํ Template์ ์ง์ ํด์ฃผ๊ณ , get_object()๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ fields ์ง์ ์ด ํ์ํฉ๋๋ค.
import os
import requests
from django.views.generic import FormView, DetailView, UpdateView
from django.urls import reverse_lazy
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login, logout
from django.core.files.base import ContentFile
from django.contrib import messages
from . import forms, models
...
...
...
class UpdateProfileView(UpdateView):
model = models.User
template_name = "users/update-profile.html"
fields = (
"first_name",
"last_name",
"avatar",
"bio",
"birthdate",
"language",
"currency",
)
def get_object(self, queryset=None):
return self.request.user
- ํ
ํ๋ฆฟ์ ๊ฐ๋จํ๊ฒ ์ง์ ํด๋ณด์ฃ . Login ํ
ํ๋ฆฟ์ ๊ทธ๋๋ก ๊ฐ์ ธ์,, social login ๋ถ๋ถ์ ์ญ์ ํ๊ณ , ์ธ์ฆ์ ๋จ๊ฒจ๋์์ด์. ๋ํ ์ธ์ฆ์ cta ๊ฐ์ "Update Profile"๋ก ์์ ํ๊ณ , "Sign Up" ๋ถ๋ถ์ "Change Password"๋ก ๋ฐ๊ฟ์ฃผ์์ด์.
{% extends "base.html" %}
{% block page_title %}
Update Profile
{% endblock page_title %}
{% block search-bar %}
{% endblock search-bar %}
{% block content %}
<div class="container lg:w-5/12 md:w-1/2 xl:w-1/4 mx-auto my-10 flex flex-col items-center border p-6 border-gray-400">
{% include 'mixins/auth/auth_form.html' with form=form cta="Update Profile" %}
<div class="mt-5">
<a href="{% url 'users:signup' %}" class="text-teal-500 font-medium">Change Password</a>
</div>
</div>
{% endblock content %}
- ์์ง ๋ ์์ฑ๋ฌ์ง๋ง, ์์ ์ ์ ๋๋๊ฒ์ ๋ณผ ์ ์์ด์. UpdateView๊ฐ ์ง์ ๋ field๋ฅผ template๋ก ์ ๋ฌํ๊ณ field์ ์์ ์ด ๋ฐ์ํ๋ฉด ์์์ ์์ ๋ฐ ์ ์ฅ์ ํด์ค๋๋ค:) ๋ํ ์์ ๋ฒํผ์ ๋๋ฅด์๋ง์ ๋ฐ๋ก profile page๋ก ๊ฐ๋ ๊ฒ์ ๋ณผ ์ ์๋๋ฐ์,, ์ด๋ UpdateView๊ฐ ์ฑ๊ณตํ๋ฉด ์๋์ผ๋ก "get_absolute_url"์ ํธ์ถํ๊ธฐ ๋๋ฌธ์
๋๋ค.
def get_absolute_url(self):
return reverse("users:profile", kwargs={"pk": self.pk})
3) PasswordChangeView
- PasswordChangeView๋ Django์์ ์ ๊ณตํ๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์์ ํ๋๋ฐ ๋์์ ์ฃผ๋ ๊ธฐ๋ฅ์ด์์. ์๋ ์์น์ ์์ต๋๋ค.
- ๐ from django.contrib.auth.views import PasswordChangeView
- "template_name"์ ์ง์ ํ์ง ์์ผ๋ฉด ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ ๋งํฌ๋ฅผ ์์ฒญํ์ ๋, admin site๋ก ๋์ด๊ฐ๋๋ค. ๊ทธ๊ฑธ ์์ง ์๊ธฐ ๋๋ฌธ์ ์ด๋ํ ํ
ํ๋ฆฟ์ ์ง์ ํด ์ฃผ์์ด์.
- ๋ํ ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ ์ฑ๊ณต์ redirectํ ๊ณณ์ ์ง์ ํด ์ฃผ์ด์ผ ์๋์ ๊ฐ์ ์ค๋ฅํ์ด์ง๋ฅผ ๋ง๋์ง ์์์. ๋น๋ฐ๋ฒํธ๋ ๋ณ๊ฒฝ๋๋ ๋ณ๊ฒฝ ํ ์ด๋ํ ๊ณณ์ ์ง์ ํด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ด์.
- success_url๋ก ์ง์ ํด์ฃผ์ด๋ ๋๊ณ , get_success_url ๋งค์๋๋ก ์ง์ ํด ์ค ์๋ ์์ต๋๋ค. ์ด๋ฒ์๋ get_success_url์ ์ฌ์ฉํด ๋ณผ๊ป์:)
- ๐ success_url = reverse_lazy('๊ฒฝ๋ก') ๐ success_url์ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด ์ด๋ ๊ฒ ์ง์ ํด์ฃผ๋ฉด๋ฉ๋๋ค.
from django.contrib.auth.views import PasswordChangeView
class UpdatePasswordView(PasswordChangeView):
template_name = "users/update-password.html"
def get_success_url(self): <
- "users/update-password.html"์ ์๋์ฒ๋ผ ์์ฑํ์์ด์.
{% extends "base.html" %}
{% block page_title %}
Update Password
{% endblock page_title %}
{% block search-bar %}
{% endblock search-bar %}
{% block content %}
<div class="min-h-75vh">
<div class="container lg:w-5/12 md:w-1/2 xl:w-1/4 mx-auto my-10 flex flex-col items-center border p-6 border-gray-400">
{% include 'mixins/auth/auth_form.html' with form=form cta="Update Password" %}
</div>
</div>
{% endblock content %}
- url์ ๋งคํํด ์ค๋๋ค.
from django.urls import path
from . import views
app_name = "users"
urlpatterns = [
...
...
path("update-password/", views.UpdatePasswordView.as_view(), name="password"),
- Profile Page์์ ๋งํฌ๋ฅผ ์ฐ๊ฒฐ์์ผ์ค๊ป์. ๋น๋ฐ๋ฒํธ๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ๋งํฌ๋ 'email'๋ก ๊ฐ์
ํ ๊ฒฝ์ฐ์๋ง ํด๋น๋์,, KaKao ๋ฑ ์ธ์ฆ์ ํตํด ๊ฐ์
ํ ๊ฒฝ์ฐ์๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์ฌ๊ธฐ์ ๋ณ๊ฒฝํ ํ์๊ฐ ์์ต๋๋ค. ๋ฐ๋ผ์, login_method ์ค 'email'๋ก ๊ฐ์
ํ ๊ฒฝ์ฐ์๋ง ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ ๋งํฌ๊ฐ ๋ํ๋๋๋ก ํ์์ด์.
{% extends "base.html" %}
{% block page_title %}
Update Profile
{% endblock page_title %}
{% block search-bar %}
{% endblock search-bar %}
{% block content %}
<div class="container lg:w-5/12 md:w-1/2 xl:w-1/4 mx-auto my-10 flex flex-col items-center border p-6 border-gray-400">
{% include 'mixins/auth/auth_form.html' with form=form cta="Update Profile" %}
{% if object.login_method == "email" %}
<div class="mt-5">
<a href="{% url 'users:password' %}" class="text-teal-500 font-medium">Change Password</a>
</div>
{% endif %}
</div>
{% endblock content %}
- "get_form"์ ๋งค์๋๋ View์์ ์ฌ์ฉ๋๋ form์ instant๋ฅผ ๋ฐํํด ์ค๋๋ค. ์ด๋ฅผ ํตํด form์ placeholder๋ฅผ ์ถ๊ฐํ๋ค๊ฑฐ๋ form์ ์ ์ดํ ์ ์์ด์.
- "get_form" ๋งค์๋๋ฅผ ํตํด form์ instant๋ฅผ ๊ฐ์ ธ์ field๊ฐ์ placeholder ์์ฑ์ ๋ฃ์ด๋ณด๋๋ก ํ ๊ป์.
- PasswordChangeView๋ฅผ ์ฌ์ฉํ ๋์๋ field์์ฑ์ ์ง์ ํด์ฃผ์ง ์์๋, form์ด ์์ฑ๋์๋๋ฐ์,, fields๊ฐ์ ์ด๋ป๊ฒ ์ ์ ์์ ๊น์? html์ฝ๋๋ฅผ ํ์ธํ์ฌ input์ name๊ฐ์ ์ง์ ํ๋ฉด ๋ฉ๋๋ค!
- fields๊ฐ : "old_password", "new_password1", "new_password2"
...
...
class UpdatePasswordView(PasswordChangeView):
template_name = "users/update-password.html"
def get_form(self):
form = super().get_form()
form.fields["old_password"].widget.attrs = {"placeholder": "Current password"}
form.fields["new_password1"].widget.attrs = {"placeholder": "New password"}
form.fields["new_password2"].widget.attrs = {"placeholder": "Confirm new password"}
return form
5) SuccessMessageMixin
- "SuccessMessageMixin"์ CBV์์ ์์๋ฐ์ ์ฌ์ฉํ๋ฉด ์ฑ๊ณตํ์ ๊ฒฝ์ฐ ์์ฝ๊ฒ ๋ฉ์์ง๋ฅผ ์ ๋ฌํ ์ ์์ด์. ํ๋กํ ์์ ๋ก์ง์ธ "UpdateProfileView" ๊ฒฝ์ฐ, ์์ ์ด ์๋ฃ๋๋ฉด ์ฑ๊ณต ๋ฉ์์ง๋ฅผ ๋ณด์ฌ์ค ์ ์์ฃ .
- "SuccessMessageMixin"๋ ์๋ ์์น์ ์์ด์.
- ๐ from django.contrib.messages.views import SuccessMessageMixin
- "success_message"์ ์ฑ๊ณต์ ๋ํ๋ผ ๋ฉ์์ง๋ฅผ ์
๋ ฅํด์ค๋๋ค.
- ๐ success_message = "Update Profile"
from django.contrib.messages.views import SuccessMessageMixin
...
...
class UpdateProfileView(SuccessMessageMixin, UpdateView):
model = models.User
template_name = "users/update-profile.html"
fields = (
"first_name",
"last_name",
"gender",
"bio",
"birthdate",
"language",
"currency",
)
success_message = "Update Profile"
def get_object(self, queryset=None):
return self.request.user
def get_form(self):
form = super().get_form()
form.fields["first_name"].widget.attrs = {"placeholder": "First name"}
form.fields["last_name"].widget.attrs = {"placeholder": "Last name"}
form.fields["gender"].widget.attrs = {"placeholder": "Gender"}
form.fields["bio"].widget.attrs = {"placeholder": "bio"}
form.fields["birthdate"].widget.attrs = {"placeholder": "Birthdate"}
form.fields["language"].widget.attrs = {"placeholder": "Language"}
form.fields["currency"].widget.attrs = {"placeholder": "Currency"}
return form
6) UserPassesTestMixin & LoginRequiredMixin
- ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธ๋ ์ํ์์๋ ๋ก๊ทธ์ธ ํ์ด์ง์ ํ์๊ฐ์
ํ์ด์ง์ ๋งํฌ๋ ๋ํ๋์ง ์์ฃ . ๋ค๋ง, ์ฌ์ฉ์๊ฐ url ์ฃผ์๋ฅผ ์๊ณ ์๋ค๋ฉด ์
๋ ฅํ์ฌ ์ ๊ทผํ ํ
๋ฐ์,, ์ฌ์ฉ์๊ฐ login์ธ ์ํ์ผ ๋ ์ด๋ฐ url์ ํตํ ์ ๊ทผ์ ๋ชปํ๊ฒํ๊ณ ์ถ๋ค๋ฉด "UserPassesTestMixin" ๊ธฐ๋ฅ์ผ๋ก ํด๊ฒฐํ ์ ์์ด์.
- ๋ํ ๋ก๊ทธ์ธํ์ง ์์ ์ฌ์ฉ์๊ฐ url ์ฃผ์๋ฅผ ์
๋ ฅํ์ฌ ์ง์ ์ ๊ทผํ์ ๋๋ ์ง์
ํ์ง ๋ชปํ๊ฒํ๊ณ Login์ ํ ์ ์๋๋ก login ํ์ด์ง๋ก ์ด๋์ํฌ ๋ "LoginRequiredMixin"๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- ์ฐ์ users ๋๋ ํ ๋ฆฌ ๋ด์ "mixin.py"๋ฅผ ์์ฑํด class๋ฅผ ์์ฑํ๊ณ "UserPassesTestMixin"์ "LoginRequiredMixin"๋ฅผ ์์๋ฐ์ต๋๋ค.
- UserPassesTestMixin"๋ฅผ ์์๋ฐ์ LoggedOutOnlyView์ "test_func" ๋งค์๋๊ฐ False๋ผ๋ฉด, "handle_no_permission" ๋งค์๋๊ฐ ์คํ๋ ๋ก๊ทธ์ธ ํ์ด์ง๋ ํ์๊ฐ์
ํ์ด์ง๋ก ์ด๋ํ์ง ์๊ณ ๋ฉ์ธ ํ์ด์ง๋ก ์ด๋ํฉ๋๋ค. ๋ํ,, "messages.error()" ๋งค์๋๋ฅผ ์ฌ์ฉํ๋ฉด, ๋ฉ์์ง๋ ์ ๋ฌํ ์ ์์ด์:)
- "LoginRequiredMixin"๋ฅผ ์์๋ฐ์ "LoggedInOnlyView"๊ฐ ์คํ๋๋ค๋ฉด, login_url๋ก redirect ๋ฉ๋๋ค.
from django.shortcuts import redirect
from django.urls import reverse_lazy
from django.contrib import messages
from django.contrib.auth.mixins import UserPassesTestMixin
class LoggedOutOnlyView(UserPassesTestMixin):
def test_func(self):
return not self.request.user.is_authenticated
def handle_no_permission(self):
messages.error(self.request, "Can't go there")
return redirect("core:home")
class LoggedInOnlyView(LoginRequiredMixin):
login_url = reverse_lazy("users:login")
- ๋ก๊ทธ์ธ ๊ธฐ๋ฅ๊ณผ ํ์๊ฐ์
๊ธฐ๋ฅ์ "LoggedOutOnlyView"์ ์์๋ฐ๊ณ , Profile Update ๊ธฐ๋ฅ๊ณผ ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ ๊ธฐ๋ฅ์ "LoggedInOnlyView"๋ฅผ ์์๋ฐ์ ์ค๋๋ค.
...
...
from . import forms, models, mixin
class LoginView(mixin.LoggedOutOnlyView, FormView): ๐
template_name = "users/login.html"
form_class = forms.LoginForm
success_url = reverse_lazy("core:home")
def form_valid(self, form):
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(self.request, username=email, password=password)
if user is not None:
login(self.request, user)
return super().form_valid(form)
...
...
class SignUpView(mixin.LoggedOutOnlyView, FormView): ๐
template_name = "users/signup.html"
form_class = forms.SignUpForm
success_url = reverse_lazy("core:home")
def form_valid(self, form):
form.save()
email = form.cleaned_data.get("email")
password = form.cleaned_data.get("password")
user = authenticate(self.request, username=email, password=password)
if user is not None:
login(self.request, user)
user.verify_email()
return super().form_valid(form)
def complete_verification(request, key):
try:
user = models.User.objects.get(email_secret=key)
user.email_verified = True
user.email_secret = ""
user.save()
except models.User.DoesNotExist:
pass
return redirect(reverse("core:home"))
...
...
class UpdateProfileView(mixin.LoggedInOnlyView, SuccessMessageMixin, UpdateView): ๐
model = models.User
template_name = "users/update-profile.html"
fields = (
"first_name",
"last_name",
"gender",
"bio",
"birthdate",
"language",
"currency",
)
...
...
class UpdatePasswordView(mixin.LoggedInOnlyView, SuccessMessageMixin, PasswordChangeView): ๐
template_name = "users/update-password.html"
success_message = "Password Updated"
def get_form(self):
form = super().get_form()
form.fields["old_password"].widget.attrs = {"placeholder": "Current password"}
form.fields["new_password1"].widget.attrs = {"placeholder": "New password"}
form.fields["new_password2"].widget.attrs = {
"placeholder": "Confirm new password"
}
return form
def get_success_url(self):
return self.request.user.get_absolute_url()
...
...