(Django) reverse와 reverse_lazy 차이

reverse와 reverse_lazy 차이

  1. reverse
  • reverse 메소드는 주어진 뷰에 대한 URL을 생성하는데 사용됩니다. 이 메서드는 URL 패턴의 이름과 뷰에 전달해야하는 인수를 받고 URL을 나타내는 문자열을 반환합니다.
  • 이 함수는 호출되는 즉시 평가(evaluated)됩니다. 즉, URL을 즉시 생성합니다.
  • reverse는 즉시 평가되기 때문에 아직 로드되지 않을 수 있는 URL 구성(configurations)(예: Django의 URL 구성에 의존하는 클래스 기반 뷰의 속성을 정의할 때)에는 사용해서는 안됩니다.
  1. reverse_lazy
  • 반면에 reverse_lazy는 reverse와 동일한 작업을 수행하지만 더 느립니다. 즉, 명시적으로 액세스(explicitly accessed)할 때까지 URL을 생성하지 않습니다.
  • 이는 success_url과 같은 클래스 기반 뷰와 같이 URLConf가 완전히 로드되지 않은 상태에서 URL을 사용해야할 때 유용합니다.

reverse_lazy는 일반적으로 클래스 기반 뷰에서 success_url을 정의할때 사용됩니다. success_url 속성은 클래스 수준(level)에서 값이 필요하지만, 이 시점에서 모든 URL 패턴이 로드되지 않을 수 있습니다. reverse_lazy를 사용하면 모든 패턴이 로드되고 실제로 URL이 필요할 때까지 URL을 연기합니다.

반면에 reverse는 LoginView의 post 메서드나 log_out 함수와 같이 메서드(함수) 내부에서 사용됩니다. 이러한 경우 메서드가 호출될때쯤이면 모든 URL 구성(configurations)이 로드될 것이므로 리버스 방식을 사용하는 것이 안전하다고 합니다.

쉬운 설명

이걸 쉬운 예시로 들면, reverse 메서드는 마법의 지도에게 지금 당장 보물로 가는 길을 알려달라고 하는 것과 같습니다. 그래서 그 마법지도는 즉시 어디로 가야하는지 알려줄 것입니다.

하지만 마법 지도가 아직 길을 그리고 있느라 준비되지 않는 경우도 있습니다. 이 경우 너무 일찍 길을 물어보면 마법 지도가 올바른 답을 줄 수 없을 것입니다. 이때 사용하는게 reverse_lazy입니다.

reverse_lazy 메서드는 마법 지도에게 "마법지도가 완성되면 보물로 가는 길을 알려줘!"라고 말하는 것과 같습니다. 그래서 마법 지도는 모든 경로를 그리고, 준비가 되면 보물이 있는 위치를 알려줍니다.

결국 마법 지도가 준비되었다는 것을 알면 reverse를 사용하고, 마법 지도가 아직 그리고 있을때는 reverse_lazy를 사용합니다.

예시 코드

class LoginView(View):
    """
    Handles user login.
    """
    template_name = "users/login.html"

    def get(self, request):
        form = LoginForm()
        return render(request, self.template_name, {"form": form})

    def post(self, request):
        form = LoginForm(request.POST)

        if form.is_valid():
            email = form.cleaned_data.get("email")
            password = form.cleaned_data.get("password")
            user = authenticate(request, email=email, password=password)

            if user:
                login(request, user)
                return redirect(reverse("users:logged_in_index"))

        return render(request, self.template_name, {"form": form})


@login_required
def log_out(request):
    """
    Logs out the user and redirects them to the index page.
    """
    logout(request)
    return redirect(reverse("users:index"))