28강

Decorator 패턴을 이용해서 자주 쓰이는 코드 간소화

 

from datetime import datetime

def function1():
	print(datetime.now())
    print("Function 1 Start")
    print(datetime.now())
    
def function2():
	print(datetime.now())
    print("Function 2 Start")
    print(datetime.now())
    
def function3():
	print(datetime.now())
    print("Function 3 Start")
    print(datetime.now())

 

->

 

def decorator(func):
	def decorated():
    	print(datetime.now())
        func()
        print(datetime.now())
        
    return decorated
from datetime import datetime
...

@decorator
def function1():
	print("Function 1 Start")

@decorator
def function2():
	print("Function 2 Start")

@decorator
def function3():
	print("Function 3 Start")

아주 간단하게 바뀜 ㅋ

 

views.py

def hello_world(request):

        if request.method == "POST":
            temp = request.POST.get('hello_world_input')

            new_hello_world=HelloWorld()
            new_hello_world.text = temp
            new_hello_world.save()
            return HttpResponseRedirect(reverse('accountapp:hello_world'))
        else:
            hello_world_list = HelloWorld.objects.all()
            return render(request, 'accountapp/hello_world.html', context={'hello_world_list':hello_world_list})
    else:
        return HttpResponseRedirect(reverse('accountapp:login'))

여기서

@login_required가 로그인 했는지 안했는지, 리턴까지 해줌

즉, @login_required가 decorator임. 이미 제공하는거지.

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, *arg, **kwargs):
        if self.request.user.is_authenticated and self.get_object() == self.request.user:
            return super().get(*arg, **kwargs)
        else:
            return HttpResponseForbidden()

    def post(self, *arg, **kwargs):
        if self.request.user.is_authenticated:
            return super().get(*arg, **kwargs)
        else:
            return HttpResponseForbidden()

이번엔 AccountUpdateView를 보자.

여기서 get이랑 post는 AccountUpdateView class가 제공하는 메소드야

(클래스에 포함된 function : 메소드, 일반적인 function : 함수. 라고 부르네?)

그니까 머 @login_required 이런거 안돼

 

views.py

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, *arg, **kwargs):
        if self.request.user.is_authenticated and self.get_object() == self.request.user:
            return super().get(*arg, **kwargs)
        else:
            return HttpResponseForbidden()

    def post(self, *arg, **kwargs):
        if self.request.user.is_authenticated:
            return super().get(*arg, **kwargs)
        else:
            return HttpResponseForbidden()

 

데코레이터 써버리면?

@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 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'

자... 그럼 그걸 하기 위해서는, custom decorator를 만들어야돼.

 

pragmatic/accountapp/templates/accountapp/decorators.py

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

? 몽미

 

@method_decorator (login_required, 'get')
@method_decorator (login_required, 'post')
@method_decorator (account_ownership_required, 'get')
@method_decorator (account_ownership_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')
@method_decorator (account_ownership_required, 'get')
@method_decorator (account_ownership_required, 'post')
class AccountDeleteView(DeleteView):
    model = User
    context_object_name = 'target_user'
    success_url = reverse_lazy('accountapp:login')
    template_name = 'accountapp/delete.html'

 

근데 method_decorator도 기니까

 

def hello_world 위에다가

has_ownership = [account_ownership_required, login_required]

하면

@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 (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'

이렇게 할 수가 있음

 


29강

superuser, media 관련 설정

superuser 계정이 있어야 들어갈 수 있어

 

 

이렇게 들어가짐.

 

이번에는 media 관련 설정을 할꺼야

 

이거 다음에 만들게 profile app인데, 거기에 이미지가 들어가거든

그래서 이미지를 올릴 수 있게 할거야

 

settings.py 맨 밑에


MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

MEDIA_URL은 주소창에 media 이하의 경로로 접근해야 실제 미디어 파일에 접근할 수 있다.

MEDIA_ROOT는 media 파일 서버에 올렸을 때, 어느 경로에 올라갈건지.

 

장고에서 이미지를 관리할 때 필요한 라이브러리가 있어

 

필로우라고 함

 

pip install pillow

 

설치하고 강의 마무리

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기