Django
미들웨어
수색…
소개
Django의 미들웨어는 코드가 응답 / 요청 처리에 연결하여 장고의 입력 또는 출력을 변경할 수있게 해주는 프레임 워크입니다.
비고
미들웨어는 실행에 포함되기 전에 settings.py MIDDLEWARE_CLASSES
목록에 추가해야합니다. Django가 새로운 프로젝트를 생성 할 때 제공하는 기본 목록은 다음과 같습니다.
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
이들은 모든 요청에 대해 순서대로 실행되는 모든 함수입니다 (한 번 views.py
에서보기 코드에 도달하기 전에 한 번, process_response
콜백의 역순으로 버전 1.10 이전에). 크로스 사이트 요청 위조 (csrf) 토큰을 주입하는 등 다양한 작업을 수행합니다.
어떤 미들웨어가 리다이렉트를하면 그 이후의 모든 미들웨어는 절대로 실행되지 않기 때문에 순서가 중요하다. 미들웨어가 csrf 토큰을 기대한다면 CsrfViewMiddleware 뒤에 실행 CsrfViewMiddleware
합니다.
요청에 데이터 추가
Django는 뷰 내에서 사용할 요청에 추가 데이터를 추가하는 것을 매우 쉽게 만듭니다. 예를 들어 요청의 META에서 하위 도메인을 파싱하고 미들웨어를 사용하여 요청시 별도의 속성으로 연결할 수 있습니다.
class SubdomainMiddleware:
def process_request(self, request):
"""
Parse out the subdomain from the request
"""
host = request.META.get('HTTP_HOST', '')
host_s = host.replace('www.', '').split('.')
request.subdomain = None
if len(host_s) > 2:
request.subdomain = host_s[0]
요청에 미들웨어가 포함 된 데이터를 추가하면 새로 추가 된 데이터에 액세스 할 수 있습니다. 여기에서는 파싱 된 하위 도메인을 사용하여 조직이 애플리케이션에 액세스하는 것과 같은 것을 결정합니다. 이 접근법은 단일 인스턴스를 가리키는 와일드 카드 하위 도메인과 함께 DNS 설정으로 배포 된 앱에 유용하며 앱에 액세스하는 사람은 액세스 포인트에 종속 된 스킨 버전을 원합니다.
class OrganizationMiddleware:
def process_request(self, request):
"""
Determine the organization based on the subdomain
"""
try:
request.org = Organization.objects.get(domain=request.subdomain)
except Organization.DoesNotExist:
request.org = None
미들웨어가 서로 의존 할 때 순서가 중요하다는 것을 기억하십시오. 요청의 경우 의존성 미들웨어가 종속성 뒤에 배치되기를 원할 것입니다.
MIDDLEWARE_CLASSES = [
...
'myapp.middleware.SubdomainMiddleware',
'myapp.middleware.OrganizationMiddleware',
...
]
IP 주소로 필터링 할 미들웨어
첫 번째 : 경로 구조
가지고 있지 않다면 다음과 같은 구조로 미들웨어 폴더를 만들어야합니다 :
yourproject/yourapp/middleware
폴더 미들웨어는 settings.py, urls, templates ...와 같은 폴더에 있어야합니다.
중요 사항 : 미들웨어 폴더 내에 init .py 빈 파일을 생성하여 앱이이 폴더를 인식하도록 잊지 마세요.
미들웨어 클래스를 포함하는 별도의 폴더를 가지는 대신, yourproject/yourapp/middleware.py
라는 단일 파일에 함수를 넣는 것도 가능합니다 .
두 번째 : 미들웨어 생성
이제 우리는 커스텀 미들웨어를위한 파일을 생성해야합니다. 이 예에서는 IP 주소를 기반으로 사용자를 필터링하는 미들웨어가 필요하다고 가정하고 filter_ip_middleware.py 라는 파일을 만듭니다.
#yourproject/yourapp/middleware/filter_ip_middleware.py
from django.core.exceptions import PermissionDenied
class FilterIPMiddleware(object):
# Check if client IP address is allowed
def process_request(self, request):
allowed_ips = ['192.168.1.1', '123.123.123.123', etc...] # Authorized ip's
ip = request.META.get('REMOTE_ADDR') # Get client IP address
if ip not in allowed_ips:
raise PermissionDenied # If user is not allowed raise Error
# If IP address is allowed we don't do anything
return None
셋째 : 우리의 'settings.py'
settings.py에서 MIDDLEWARE_CLASSES
를 찾아야하고 거기에 미들웨어를 추가해야합니다 ( 마지막 위치에 추가 ). 그것은 다음과 같아야합니다 :
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Above are Django standard middlewares
# Now we add here our custom middleware
'yourapp.middleware.filter_ip_middleware.FilterIPMiddleware'
)
끝난! 이제 모든 클라이언트의 모든 요청이 사용자 정의 미들웨어를 호출하고 사용자 정의 코드를 처리합니다!
전역 적 예외 처리
변경 사항을 제출 한 클라이언트가 최신 수정 사항을 가지고 있지 않은 동안 데이터베이스의 객체 수정 시도를 탐지하는 로직을 구현했다고 가정 해보십시오. 이러한 경우가 발생하면 사용자 정의 예외 ConfictError(detailed_message)
합니다.
이제이 오류가 발생할 때 HTTP 409 (Confict) 상태 코드를 반환하려고합니다. 일반적으로이 예외를 발생시킬 수있는 각 뷰에서이를 처리하는 대신 미들웨어로 사용할 수 있습니다.
class ConfictErrorHandlingMiddleware:
def process_exception(self, request, exception):
if not isinstance(exception, ConflictError):
return # Propagate other exceptions, we only handle ConflictError
context = dict(confict_details=str(exception))
return TemplateResponse(request, '409.html', context, status=409)
Django 1.10 미들웨어의 새로운 스타일 이해하기
Django 1.10에서는 process_request
와 process_response
가 함께 병합되는 새로운 미들웨어 스타일을 도입했습니다.
이 새로운 스타일에서 미들웨어는 다른 호출 가능 객체를 반환하는 호출 가능 객체 입니다. 글쎄, 실제로는 전자는 미들웨어 공장 이고 후자는 실제 미들웨어 입니다.
미들웨어 팩토리 는 미들웨어 스택의 다음 미들웨어 를 단일 인수로 취하고, 스택의 맨 아래에 도달하면 뷰 자체를 취합니다.
미들웨어 는 요청을 하나의 인수 로 HttpResponse
항상 HttpResponse
반환합니다 .
새로운 스타일의 미들웨어가 작동하는 방식을 보여주는 가장 좋은 예는 아마도 이전 버전과 호환되는 미들웨어 를 만드는 방법을 보여주는 것입니다.
class MyMiddleware:
def __init__(self, next_layer=None):
"""We allow next_layer to be None because old-style middlewares
won't accept any argument.
"""
self.get_response = next_layer
def process_request(self, request):
"""Let's handle old-style request processing here, as usual."""
# Do something with request
# Probably return None
# Or return an HttpResponse in some cases
def process_response(self, request, response):
"""Let's handle old-style response processing here, as usual."""
# Do something with response, possibly using request.
return response
def __call__(self, request):
"""Handle new-style middleware here."""
response = self.process_request(request)
if response is None:
# If process_request returned None, we must call the next middleware or
# the view. Note that here, we are sure that self.get_response is not
# None because this method is executed only in new-style middlewares.
response = self.get_response(request)
response = self.process_response(request, response)
return response