Django 템플릿 내 사이트의 도메인 이름을 얻으려면 어떻게해야합니까?


답변:


67

원하는 것은 요청 컨텍스트에 액세스하는 것입니다. RequestContext를 참조하십시오.


140
request.META['HTTP_HOST']도메인을 제공합니다. 템플릿에서는입니다 {{ request.META.HTTP_HOST }}.
Daniel Roseman

29
요청 메타 데이터 사용에주의하십시오. 브라우저에서 제공되며 스푸핑 될 수 있습니다. 일반적으로 @CarlMeyer가 제안하는 내용을 사용하고 싶을 것입니다.
Josh

2
내 목적으로는 보안상의 허점이 없습니다.
Paul Draper

7
허용 된 호스트 설정으로 Django 1.5 이후로 사용하는 것이 안전하다고 생각합니다. docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
Daniel Backman

8
누군가 "보안 허점"이 무엇인지 자세히 설명 할 수 있습니까? 사용자가 Host:헤더를 스푸핑하고 페이지의 어딘가에서 스푸핑 된 도메인으로 응답을 받으면 어떻게 보안 허점을 만들 수 있습니까? 생성 된 HTML을 가져 와서 자신의 브라우저에 공급하기 전에 자신을 수정하는 사용자와 어떻게 다른지 알 수 없습니다.
user193130 2016 년

105

실제 HTTP 호스트 헤더를 원하면 @Phsiao의 답변에 대한 Daniel Roseman의 의견을 참조하십시오. 다른 대안은 contrib.sites 프레임 워크를 사용하는 경우 데이터베이스의 사이트에 대한 표준 도메인 이름을 설정할 수 있습니다 (요청 도메인을 올바른 SITE_ID를 사용하여 설정 파일로 매핑하는 것은 사용자가 직접 수행해야하는 것임) 웹 서버 설정). 이 경우 찾고 있습니다 :

from django.contrib.sites.models import Site

current_site = Site.objects.get_current()
current_site.domain

current_site 객체를 사용하려면 템플릿 컨텍스트에 current_site 객체를 직접 넣어야합니다. 모든 곳에서 사용하는 경우 템플릿 컨텍스트 프로세서로 패키지화 할 수 있습니다.


3
내가 가진 것과 동일한 문제가있는 사람을 명확히하려면 : SITE_ID설정이 id사이트 앱의 현재 사이트 속성 과 같은지 확인합니다 ( id사이트 관리자 패널에서 찾을 수 있음 ). 를 호출 get_current하면 Django가 사용자를 가져 와서 해당 ID를 가진 객체를 데이터베이스에서 SITE_ID반환 Site합니다.
Dennis Golomazov

이 중 어느 것도 나를 위해 일하지 않습니다. print("get_current_site: ", get_current_site(request)) print("absolute uri: ", request.build_absolute_uri()) print("HTTP_HOST: ", request.META['HTTP_HOST']) get_current_site: localhost:8001 absolute uri: http://localhost:8001/... HTTP_HOST: localhost:8001
user251242

86

나는 그 {{ request.get_host }}방법을 발견했다 .


11
이 답변에는 Daniel Roseman 접근 방식과 동일한 문제가 있지만 (스푸핑 될 수 있음) HTTP_X_FORWARDED_HOSTHTTP 헤더 를 고려하기 때문에 HTTP 프록시 또는로드 밸런서를 통해 호스트에 도달하면 더 완벽합니다 .
furins

4
사용법 : "// {{request.get_host}} / anything / else / you / want"... ALLOWED_HOSTS 설정을 입력하십시오 ( docs.djangoproject.com/en/1.5/ref/settings/#allowed 참조) . -호스트 ).
세스

3
@Seth를 사용하는 것이 좋습니다 request.build_absolute_uri( docs.djangoproject.com/en/dev/ref/request-response/… )
MrKsn

60

Carl Meyer를 보완하면 다음과 같은 컨텍스트 프로세서를 만들 수 있습니다.

module.context_processors.py

from django.conf import settings

def site(request):
    return {'SITE_URL': settings.SITE_URL}

로컬 설정 .py

SITE_URL = 'http://google.com' # this will reduce the Sites framework db call.

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

URL 사이트가 컨텍스트 인스턴스를 반환하는 템플릿은 {{SITE_URL}}입니다.

컨텍스트 프로세서에서 하위 도메인 또는 SSL을 처리하려는 경우 자체 루틴을 작성할 수 있습니다.


나는이 솔루션을 시도했지만 동일한 응용 프로그램에 대한 여러 하위 도메인이있는 경우 실용적이지 않습니다. danbruegge의 답변이 매우 유용하다는 것을 알았습니다
Jose Luis de la Rosa

settings.py에서 context_processors> OPTIONS> TEMPLATES
yas17

24

내가 사용하는 컨텍스트 프로세서의 변형은 다음과 같습니다.

from django.contrib.sites.shortcuts import get_current_site
from django.utils.functional import SimpleLazyObject


def site(request):
    return {
        'site': SimpleLazyObject(lambda: get_current_site(request)),
    }

SimpleLazyObject래퍼 템플릿이 실제로 사용하면 DB 호출에만 발생 확인합니다site 개체를. 관리 페이지에서 쿼리가 제거됩니다. 또한 결과를 캐시합니다.

설정에 포함하십시오.

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
)

템플릿 {{ site.domain }}에서 현재 도메인 이름을 얻는 데 사용할 수 있습니다 .

편집 : 프로토콜 전환도 지원 하려면 다음 을 사용하십시오.

def site(request):
    site = SimpleLazyObject(lambda: get_current_site(request))
    protocol = 'https' if request.is_secure() else 'http'

    return {
        'site': site,
        'site_root': SimpleLazyObject(lambda: "{0}://{1}".format(protocol, site.domain)),
    }

SimpleLazyObject어쨌든 '사이트'에 액세스하는 것이 없으면 람다가 호출 되지 않으므로 여기에서 사용할 필요가 없습니다 .
monokrome

를 제거하면 SimpleLazyObject각각 RequestContext이를 호출 get_current_site()하여 SQL 쿼리를 실행합니다. 랩퍼는 변수가 실제로 템플리트에서 사용될 때만 평가되도록합니다.
vdboor

1
함수이므로 호스트 문자열은 어쨌든 사용되지 않으면 처리되지 않습니다. 따라서 'site_root'에 함수를 할당하면 SimpleLazyObject가 필요하지 않습니다. Django는 사용될 때 함수를 호출합니다. 어쨌든 람다로 필요한 기능을 이미 만들었습니다.
monokrome

아, 람다 만 작동합니다. 는 SimpleLazyObject이후 정말 필요하지 않은 기능의 재평가 방지하기 위해이 Site객체가 캐시됩니다.
vdboor

수입은 지금from django.contrib.sites.shortcuts import get_current_site
Hraban

22

나는이 질문이 오래되었다는 것을 알고 있지만 현재 도메인을 얻는 파이썬적인 방법을 찾고 있습니다.

def myview(request):
    domain = request.build_absolute_uri('/')[:-1]
    # that will build the complete domain: http://foobar.com

4
build_absolute_uri여기 에 문서화되어 있습니다 .
Philipp Zedler

19

빠르고 간단하지만 생산에는 좋지 않습니다.

(보기에서)

    request.scheme               # http or https
    request.META['HTTP_HOST']    # example.com
    request.path                 # /some/content/1/

(템플릿에서)

{{ request.scheme }} :// {{ request.META.HTTP_HOST }} {{ request.path }}

render를 사용하는 경우 RequestContext 를 사용해야합니다 .

request.META['HTTP_HOST']프로덕션을 신뢰하지 마십시오 . 해당 정보는 브라우저에서 제공됩니다. 대신 @CarlMeyer의 답변을 사용하십시오.


이 답변을지지하지만 사용하려고 할 때 오류가 발생했습니다 request.scheme. 아마도 최신 버전의 장고에서만 사용할 수 있습니다.
매트 크림

@MattCremeens request.scheme가 Django 1.7에 추가되었습니다.
S. Kirby

16

{{ request.get_host }}ALLOWED_HOSTS설정 과 함께 사용될 때 HTTP 호스트 헤더 공격으로부터 보호해야 합니다 (Django 1.4.4에 추가됨).

참고 {{ request.META.HTTP_HOST }}동일한 보호가 없습니다. 문서를 참조하십시오 :

ALLOWED_HOSTS

이 장고 사이트가 제공 할 수있는 호스트 / 도메인 이름을 나타내는 문자열 목록입니다. 이것은 HTTP 호스트 헤더 공격 을 방지하기위한 보안 조치입니다. 웹 서버 , 많은 안전한 웹 서버 구성에서도 가능합니다.

... Host헤더 (또는 활성화 된 X-Forwarded-Host경우 USE_X_FORWARDED_HOST)가이 목록의 값과 일치하지 않으면 django.http.HttpRequest.get_host()메서드가 발생 SuspiciousOperation합니다.

...이 검증은 다음을 통해서만 적용됩니다 get_host(). 코드가 직접 호스트 헤더에 액세스하는 request.META경우이 보안 보호를 우회합니다.


request템플릿에서 를 사용하면 Django 1.8에서 템플릿 렌더링 함수 호출이 변경되어 더 이상 처리 할 필요가 없습니다.RequestContext 직접 할 .

바로 가기 기능을 사용하여 뷰의 템플릿을 렌더링하는 방법은 다음과 같습니다 render().

from django.shortcuts import render

def my_view(request):
    ...
    return render(request, 'my_template.html', context)

이메일을위한 템플릿을 렌더링하는 방법은 다음과 같습니다. IMO는 호스트 값을 원하는 가장 일반적인 경우입니다.

from django.template.loader import render_to_string

def my_view(request):
    ...
    email_body = render_to_string(
        'my_template.txt', context, request=request)

다음은 이메일 템플릿에 전체 URL을 추가하는 예입니다. request.scheme는 얻어야한다 http또는 https당신이 사용중인에 따라 :

Thanks for registering! Here's your activation link:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %}

10

맞춤 템플릿 태그를 사용합니다. 예를 들어 <your_app>/templatetags/site.py다음과 같이 추가하십시오 .

# -*- coding: utf-8 -*-
from django import template
from django.contrib.sites.models import Site

register = template.Library()

@register.simple_tag
def current_domain():
    return 'http://%s' % Site.objects.get_current().domain

다음과 같은 템플릿에서 사용하십시오.

{% load site %}
{% current_domain %}

이 접근법에 대한 특별한 단점이 있습니까? 모든 요청에 ​​대한 사이트 DB 호출 외에.
kicker86

@ kicker86 몰라요. get_current문서화 된 방법입니다. docs.djangoproject.com/en/dev/ref/contrib/sites/…
Dennis Golomazov

3
'http://%s'https연결시 문제가 될 수 있습니다 . 이 경우 체계가 역동적이지 않습니다.
손상된 유기

4

사용자 panchicore의 답변과 유사하게 이것은 매우 간단한 웹 사이트에서 한 일입니다. 몇 가지 변수를 제공하고 템플릿에서 사용할 수있게합니다.

SITE_URL같은 값 example.com
SITE_PROTOCOL을 보유 http 하거나 https
SITE_PROTOCOL_URL같은 값 을 보유 http://example.com하거나https://example.com
SITE_PROTOCOL_RELATIVE_URL//example.com .

module / context_processors.py

from django.conf import settings

def site(request):

    SITE_PROTOCOL_RELATIVE_URL = '//' + settings.SITE_URL

    SITE_PROTOCOL = 'http'
    if request.is_secure():
        SITE_PROTOCOL = 'https'

    SITE_PROTOCOL_URL = SITE_PROTOCOL + '://' + settings.SITE_URL

    return {
        'SITE_URL': settings.SITE_URL,
        'SITE_PROTOCOL': SITE_PROTOCOL,
        'SITE_PROTOCOL_URL': SITE_PROTOCOL_URL,
        'SITE_PROTOCOL_RELATIVE_URL': SITE_PROTOCOL_RELATIVE_URL
    }

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    "module.context_processors.site",
    ....
 )

SITE_URL = 'example.com'

그런 다음, 템플릿,로 사용 {{ SITE_URL }}, {{ SITE_PROTOCOL }}, {{ SITE_PROTOCOL_URL }}{{ SITE_PROTOCOL_RELATIVE_URL }}


2

Django 템플릿에서 다음을 수행 할 수 있습니다.

<a href="{{ request.scheme }}://{{ request.META.HTTP_HOST }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>

1
감사합니다. 나는, 템플릿 요청을 수 있도록 context_processors을했다 : django.template.context_processors.request또한 [이 어떻게에 도움] ( simpleisbetterthancomplex.com/tips/2016/07/20/... )
ionescu77

Vitor Freitas 블로그는 Django 개발자를위한 훌륭한 소스입니다! :)
Dos

2

당신이 사용하는 경우 "요청"상황에 맞는 프로세서를 하고 사용하는 장고 사이트 프레임 워크를 하고있는 사이트 미들웨어 설치 (즉, 설정은 다음을 포함한다) :

INSTALLED_APPS = [
    ...
    "django.contrib.sites",
    ...
]

MIDDLEWARE = [
    ...
     "django.contrib.sites.middleware.CurrentSiteMiddleware",
    ...
]

TEMPLATES = [
    {
        ...
        "OPTIONS": {
            "context_processors": [
                ...
                "django.template.context_processors.request",
                ...
            ]
        }
    }
]

... 그러면 request템플릿 에서 객체를 사용할 수 있으며 현재에 대한 참조가 포함됩니다Site 요청 대한 됩니다 request.site. 그런 다음 다음을 사용하여 템플릿에서 도메인을 검색 할 수 있습니다.

    {{request.site.domain}}

1

이 방법은 어떻습니까? 나를 위해 작동합니다. django-registration 에서도 사용됩니다 .

def get_request_root_url(self):
    scheme = 'https' if self.request.is_secure() else 'http'
    site = get_current_site(self.request)
    return '%s://%s' % (scheme, site)

그러나 그것을 시도하면 정적 URL이있는 경우 작동하지 않는 체계 (안전하다고 간주 됨)를 localhost얻을 수 있습니다 https( http://127.0.0.1유효하지 않습니다 https://127.0.0.1). 따라서 개발 중에는 이상적이지 않습니다.
ThePhi

0
from django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)

-5

당신이 사용할 수있는 {{ protocol }}://{{ domain }}도메인 이름을 얻을 수 있도록 템플릿에서.


@Erwan은 이것이 비표준 요청 컨텍스트 프로세서에 의존한다는 것을 알지 못합니다.
monokrome

프로토콜과 도메인을 어디에서 정의합니까?
Jose Luis de la Rosa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.