web-dev-qa-db-ja.com

Djangoテンプレート内でサイトのドメイン名を取得するにはどうすればよいですか?

Djangoテンプレート内から現在のサイトのドメイン名を取得するにはどうすればよいですか?タグとフィルターを調べてみましたが、何もありませんでした。

143
mog

あなたが望むのは、リクエストコンテキストにアクセスできることだと思います。RequestContextを参照してください。

60
phsiao

実際のHTTP Hostヘッダーが必要な場合は、@ Phsiaoの回答に関するDaniel Rosemanのコメントを参照してください。他の選択肢は、 contrib.sites framework を使用している場合、データベース内のサイトに正規のドメイン名を設定できます(適切なSITE_IDを持つ設定ファイルに要求ドメインをマッピングすることです)ウェブサーバーの設定で自分で行う必要があります)。その場合、あなたは探しています:

from Django.contrib.sites.models import Site

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

current_siteオブジェクトを使用する場合は、自分でテンプレートコンテキストに入れる必要があります。あらゆる場所で使用している場合は、テンプレートコンテキストプロセッサにパッケージ化できます。

94
Carl Meyer

{{ request.get_Host }} メソッドを発見しました。

74
danbruegge

Carl Meyerを補完して、次のようなコンテキストプロセッサを作成できます。

module.context_processors.py

from Django.conf import settings

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

local settings.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を処理する場合は、独自のルーティンを作成できます。

56
panchicore

私が使用するコンテキストプロセッサのバリエーションは次のとおりです。

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ラッパーは、テンプレートが実際にsiteオブジェクトを使用する場合にのみDB呼び出しが行われるようにします。これにより、管理ページからクエリが削除されます。結果もキャッシュします。

それを設定に含めます:

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)),
    }
24
vdboor

私はこの質問が古いことを知っていますが、現在のドメインを取得するためのPythonicな方法を探していました。

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

迅速でシンプルですが、生産には適していません。

(ビュー内)

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

(テンプレート内)

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

必ず RequestContext を使用してください。これは render を使用している場合に当てはまります。

本番環境でrequest.META['HTTP_Host']を信頼しないでください。その情報はブラウザから取得されます。代わりに、@ CarlMeyerの答えを使用してください

15
Edward Newell

{{ request.get_Host }}ALLOWED_HOSTS設定(Django 1.4.4で追加)と組み合わせて使用​​すると、HTTPホストヘッダー攻撃から保護する必要があります。

{{ request.META.HTTP_Host }}には同じ保護機能がないことに注意してください。 docs を参照してください:

ALLOWED_HOSTS

このDjangoサイトが提供できるホスト/ドメイン名を表す文字列のリスト。これは HTTPホストヘッダー攻撃 を防ぐためのセキュリティ対策です。

... Hostヘッダー(またはX-Forwarded-Hostが有効になっている場合はUSE_X_FORWARDED_Host)がこのリストのどの値とも一致しない場合、Django.http.HttpRequest.get_Host()メソッドはSuspiciousOperationを発生させます。 。

...この検証は、get_Host()を介してのみ適用されます。コードがrequest.METAから直接Hostヘッダーにアクセスする場合、このセキュリティ保護をバイパスしています。


テンプレートでrequestを使用する場合、テンプレートレンダリング関数の呼び出しには Django 1.8で変更 があるため、RequestContextを処理する必要はありません。直接。

ショートカット関数render()を使用して、ビューのテンプレートをレンダリングする方法は次のとおりです。

from Django.shortcuts import render

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

メールのテンプレートをレンダリングする方法は次のとおりです。IMOは、Host値が必要な場合のより一般的なケースです。

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 %}
13
S. Kirby

カスタムテンプレートタグを使用します。例に追加<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 %}
8

ユーザーpanchicoreの返信と同様、これは非常にシンプルなWebサイトで行ったことです。いくつかの変数を提供し、テンプレートで使用できるようにします。

SITE_URLexample.comのような値を保持します
SITE_PROTOCOLは、httphttpsなどの値を保持します
SITE_PROTOCOL_URLは、http://example.comhttps://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 }}として使用します

3

Djangoテンプレートでは、次のことができます。

<a href="{{ request.scheme }}://{{ request.META.HTTP_Host }}{{ request.path }}?{{ request.GET.urlencode }}" >link</a>
0
Dos
from Django.contrib.sites.models import Site
if Site._meta.installed:
    site = Site.objects.get_current()
else:
    site = RequestSite(request)
0
Muneeb Ahmad

このアプローチはどうですか?私のために働く。 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)
0
user9434062