1. Authentication 기능 구현
메인 페이지 접근 제한
로그인한 사용자만 메인 페이지에 접근할 수 있도록 아래 코드와 같이 접근 제한 코드를 추가한다. 특별할게 없고, 기존 코드를 if, else 문으로 감싸서 처리한다. django에서 제공해주는 requet.user.is_authenticated로 로그인 여부를 검사할 수 있다. 로그인이 되지 않았다면 HttpResponseRedirect를 이용해서 로그인 페이지로 보내도록 한다.
views.py
def hello_world(request):
if request.user.is_authenticated:
if request.method == 'POST':
#기존 코드 생략
else:
return HttpResponseRedirect(reverse('accountapp:login'))
각 뷰 접근 제한
각 뷰에 접근 제한을 해본다. class로 작성했기 때문에, 상속받는 UpdateView, DeleteView에서 제공하는 get, post '메서드'를 사용할 수 있다. 참고로 파이썬에서는 class 내부의 def는 '메서드', 위 메인 페이지용 def 자체는 '함수'라고 구분한다.
views.py
각 메서드에서 is_authenticated를 사용하였다. 로그인 여부 뿐만 아니라 메서드에서 받아오는 target_user가 실제 로그인한 user와 일치하는지 여부를 확인하기 위해서 self.get_object() = self.request.user 구문을 사용하였다. self는 각 클래스를 의미하고, get_object()는 각 class에서 사용하는 model, 즉 user 객체를 가져온다.
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountapp:hello_world')
template_name = 'accountapp/update.html'
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountapp:login')
template_name = 'accountapp/delete.html'
def get(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().get(*args, **kwargs)
else:
return HttpResponseForbidden()
def post(self, *args, **kwargs):
if self.request.user.is_authenticated and self.get_object() == self.request.user:
return super().post(*args, **kwargs)
else:
return HttpResponseForbidden()
또한 HttpResponseForbidden()을 사용하였다. 이제 로그인한 사용자가 다른 사용자의 update, delete 페이지로 접근하면 403 에러가 발생한다.
2. Decorator 적용하기
Decorator란
간단하게 말하자면 함수의 주요 기능 외 부가적인 기능들을 공통화하여 처리함으로써 코드의 가독성을 높일 수 있는 방법이다. 강의에서 드는 예시로, 어떤 함수의 실행 전과 후의 시각을 출력하는 함수가 있다고 해보자. 그러면 아래와 같이 decorator를 적용하여 반복적인 작업을 줄이고 코드의 가독성을 높일 수 있다.
def function():
print(datetime.now())
print("function process")
print(datetime.now())
#decorator 적용 코드
@decorator
def function():
print("function process")
#decorator 코드
def decorator(func):
def decorated():
print(datetime.now())
func()
print(datetime.now())
return decorated
@login_required, @method_decorator
django에서 기본적으로 제공하는 @login_required를 적용할 수 있다. 직관적으로 알 수 있듯이 로그인 이후에만 해당 함수 또는 메서드에 접근가능하도록 한다는 것이다.
메인 페이지 '함수'에 적용(views.py)
@login_required
def hello_world(request):
if request.method == 'POST':
#로직 생략
클래스뷰 '메서드'에 적용
클래스 내부에 있는 메서드에 적용하기 위해서는 @method_decorator()를 써줘야한다.
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountapp:hello_world')
template_name = 'accountapp/update.html'
@method_decorator(login_required, 'get')
@method_decorator(login_required, 'post')
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountapp:login')
template_name = 'accountapp/delete.html'
커스텀 데코레이터 적용
그런데 login_required는 단순히 로그인 여부만 체크할뿐, 페이지의 pk와 로그인한 유저의 pk가 일치하는지는 검사하지 않는다. 따라서 이 기능을 추가하기 위해서 커스텀 데코레이터를 만든다.
accountapp/decorators.py
User.objects.get(pk=kwargs['pk']로 키워드 인자로 'pk'라는 이름의 객체를 가져온다는 것을 아아두자.
from django.contrib.auth.models import User
from django.http import HttpResponseForbidden
def account_ownership_required(func):
def decorated(request, *args, **kwargs):
user = User.objects.get(pk=kwargs['pk'])
if not user == request.user:
return HttpResponseForbidden()
return func(request, *args, **kwargs)
return decorated
views.py
이제 @method_decorator로 커스텀 데코레이터로 작성한 account_ownership_required를 넣어주면 된다. 적용해야할 데코데이터가 여러 개라면, 최상단에 선언한 has_ownership 처럼 리스트를 만들어서 여러 개의 데코레이터를 한번에 적용하는 것도 가능하다.
has_ownership = [
login_required, account_ownership_required
]
###중략...
# @method_decorator(login_required, 'get')
# @method_decorator(login_required, 'post')
# @method_decorator(account_ownership_required, 'get')
# @method_decorator(account_ownership_required, 'post')
@method_decorator(has_ownership, 'get')
@method_decorator(has_ownership, 'post')
class AccountUpdateView(UpdateView):
model = User
context_object_name = 'target_user'
form_class = AccountUpdateForm
success_url = reverse_lazy('accountapp:hello_world')
template_name = 'accountapp/update.html'
# @method_decorator(login_required, 'get')
# @method_decorator(login_required, 'post')
# @method_decorator(account_ownership_required, 'get')
# @method_decorator(account_ownership_required, 'post')
@method_decorator(has_ownership, 'get')
@method_decorator(has_ownership, 'post')
class AccountDeleteView(DeleteView):
model = User
context_object_name = 'target_user'
success_url = reverse_lazy('accountapp:login')
template_name = 'accountapp/delete.html'
3. Superuser 및 media 설정
다음 강의를 위한 세팅 부분이라고 보면 된다.
SuperUser
계정생성
superuser를 생성하기 위해서 'pyhton manage.py createsuperuser' 명령어를 터미널에 입력하고 username, password를 설정한다.
그리고 pragmatic/urls.py에 기본으로 설정된 admin 페이지에 접속해본다.
로그인을 하면 관리자 페이지가 나오고, 기본적으로 생성돼있던 Model들이 보인다. 앞으로 사이트를 구축하면서 모델들이 추가되면 여기서 다 조회가 된다고 한다. 그리고 django에서 제공해주는 이 기본 admin 페이지의 기능도 상당히 좋아서, 살펴보면 상당한 내용들이 있다고 한다.
MEDIA 설정
마지막으로 MEDIA 설정을 한다. static과 같이 media 파일들을 올릴 때 기본이 되는 MEDIA_URL과 media 파일들이 모이는 MEDIA_ROOT 위치를 설정해준다.
settings.py 일부
MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
그리고 Media 파일은 git에 올라갈 필요가 없으므로 .gitignore에 추가해준다.
gitignore에 추가
media/
참조
1. 작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지-박형석님 인프런 강의
'Programming-[Backend] > Django' 카테고리의 다른 글
Django로 Pinterest 따라 만들기-10. Profileapp 마무리, 리팩토링 (0) | 2022.06.10 |
---|---|
Django로 Pinterest 따라 만들기-9. ModelForm 사용, Profileapp 구현 (0) | 2022.06.09 |
Django로 Pinterest 따라 만들기-7. Update, DeleteView 구현 (0) | 2022.06.09 |
Django로 Pinterest 따라 만들기-6. BootStrap 추가, DetailView 구현 (0) | 2022.06.08 |
Django로 Pinterest 따라 만들기-5. AccountApp : CBV, CreateView, Login, reverse_lazy (0) | 2022.06.08 |