Djangoで完全/絶対URL(ドメイン付き)を取得するにはどうすればよいですか?


379

Sitesモジュールなしhttps://example.com/some/pathでDjango の完全/絶対URL(例:) を取得するにはどうすればよいですか?それはばかげているだけです... URLを取得するためにDBをクエリする必要はありません!

で使いたいreverse()


11
余談ですが、サイトモジュールは最初にサイト名が必要になったときにのみDBにアクセスし、結果はモジュール変数(SITE_CACHE)にキャッシュされます。メソッドが呼び出されます。参照:code.djangoproject.com/svn/django/tags/releases/1.3/django/...
大佐Sponsz

回答:


512

リクエストに応じて便利なrequest.build_absolute_uri()メソッドを使用し、それに相対URLを渡すと、完全なURLが得られます。

デフォルトではの絶対URL request.get_full_path()が返されますが、相対URLを最初の引数として渡して絶対URLに変換できます。


3
URL:localhost / home /#/ testはどうですか?localhost / homeしか表示されません。鋭利な部分をどのように見ることができますか?
sergzach 2011

41
#以降のすべてはサーバーに渡されず、ブラウザーのみの機能です
Dmitry Shevchenko '19

70
テンプレートでは(パラメーターを指定できない場合)、次のようにすることができます:{{ request.build_absolute_uri }}{{ object.get_absolute_url }}-heyho、完全なURL。
odinho-Velmont 2013年

17
また、リクエストへのアクセス権がない場合はどうなりますか?Django-REST-Frameworkのシリアライザのように?
マインダー

15
末尾にスラッシュがあり、スラッシュで始まっているため、URLに二重スラッシュが使用さ{% if request.is_secure %}https://{% else %}http://{% endif %}{{ request.get_host }}{{ object.get_absolute_url }}{{ request.build_absolute_uri }}ていたため、使用する必要があり{{ object.get_absolute_url }}ました。
エクストラノフィリスト

96

あなたがそれを使いたいreverse()なら、これを行うことができます:request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))


3
役立つ回答をありがとう。コード自体に勝るものはありません。(また、おそらくのurl_name代わりにを意味していましたview_name
Anupam

3
@Anupam逆を()のように定義される:def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
マティアスelgart

57

get_current_siteサイトアプリ(from django.contrib.sites.models import get_current_site)の一部として使用することもできます。リクエストオブジェクトを受け取り、リクエストがの場合、デフォルトSITE_IDでsettings.pyで設定したサイトオブジェクトになりますNoneサイトフレームワークの使用に関するドキュメントで詳細を読む

例えば

from django.contrib.sites.shortcuts import get_current_site
request = None
full_url = ''.join(['http://', get_current_site(request).domain, obj.get_absolute_url()])

ほどコンパクトrequest.build_absolute_url()ではありませんが、リクエストオブジェクトが利用できず、デフォルトのサイトURLがある場合に使用できます。


4
私の質問は特に「サイトモジュールなしで」と言っていたと思います。これはDBに影響しますか?
mpen 2012年

1
Sitesモジュールは、モジュールレベルのキャッシュを使用してSiteオブジェクトをキャッシュするように作成されているため(つまり、キャッシュフレームワークは必要ありません)、DBは、サイトがWebプロセスによって初めて取得されたときにのみヒットします。あなたが持っていない場合はdjango.contrib.sites、あなたの中でINSTALLED_APPS、それがすべてでDBをヒットしないだろう、と(参照Requestオブジェクトに基づいて情報を提供get_current_site
DARB

1
さて、あなたは+1を持つことができますが、build_absolute_uriそれでも簡単でクリーンな解決策のように見えます。
mpen 2012年

1
これは、電子メールをディスパッチする信号でURLを生成しようとしている場合の完全な回答です。
Chris

2
httpsを使用している場合は機能しません。ええ、あなたはsを追加することができますが、ローカルでhttpsを使用して開発しますか?そして、あなたはいつも知っていますか?
tjati 2014

55

アクセスできないrequest場合はget_current_site(request)、こちらのソリューションで推奨されているとおりに使用できません。get_absolute_url代わりに、ネイティブのSitesフレームワークを組み合わせて使用​​できます。管理者に少なくとも1つのサイトを設定し、モデルにget_absolute_url()メソッドがあることを確認してから、次のようにします。

>>> from django.contrib.sites.models import Site
>>> domain = Site.objects.get_current().domain
>>> obj = MyModel.objects.get(id=3)
>>> path = obj.get_absolute_url()

>>> url = 'http://{domain}{path}'.format(domain=domain, path=path)
>>> print(url)
'http://example.com/mymodel/objects/3/'

https://docs.djangoproject.com/en/dev/ref/contrib/sites/#getting-the-current-domain-for-full-urls


7
これは、HttpRequestオブジェクトにアクセスできない場合に非常に便利です。例:タスク、信号など
Arsham 2014

6
これを使用する前に、サイトフレームワークdocs.djangoproject.com/en/dev/ref/contrib/sites/…
madzohan

example.comを何かに変更するには:Site.objects.all()[0]は 'example.com'を返し、settings.pyで指定されているid = 1を持っています。Site.objects.create(name = 'production'、domain = 'prodsite.com')を実行し、settings.pyでSITE_ID = 2を設定するだけです。これでSite.objects.get_current()。domainは「prodsite.com」を返します。
GEK

あなたは、設定することができますrequestNoneまたはコールget_current_site(None)
Bobort

20

データベースにアクセスしたくない場合は、設定を使用して実行できます。次に、コンテキストプロセッサを使用してすべてのテンプレートに追加します。

# settings.py (Django < 1.9)
...
BASE_URL = 'http://example.com'
TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'myapp.context_processors.extra_context',
)
# settings.py (Django >= 1.9)
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                # Additional
                'myapp.context_processors.extra_context',
            ],
        },
    },
]

# myapp/context_processors.py
from django.conf import settings

def extra_context(request):
    return {'base_url': settings.BASE_URL}

# my_template.html
<p>Base url is {{ base_url }}.</p>

17

あなたの見解では、これをしてください:

base_url =  "{0}://{1}{2}".format(request.scheme, request.get_host(), request.path)

14

django-fullurl

あなたはDjangoテンプレートでこれをやろうとしている場合、私は小さなは、PyPIパッケージリリースしたdjango-fullurlあなたが代わっするurlstatic、テンプレートタグをとfullurlしてfullstatic、このように:

{% load fullurl %}

Absolute URL is: {% fullurl "foo:bar" %}

Another absolute URL is: {% fullstatic "kitten.jpg" %}

これらのバッジは、うまくいけば自動的に最新の状態に保たれるはずです。

PyPI トラビスCI

ビューでは、もちろんrequest.build_absolute_uri代わりに使用できます。


残念ながら、これは2.0では機能しません。PRを押し上げる必要があるかもしれません。
スティーブンチャーチ

@StevenChurch動作するはずです。Django 2.0をサポート対象としてマークしていませんが、既存のバージョンで動作するはずです。
Flimm

私のニーズのために、フェローバックのためにHerokuからENVを渡すことでこれを回避しました。私の問題は、メールテンプレートに渡すURLを取得することです。問題を思い出せませんが、Djangoの変更により機能しませんでした。
スティーブン教会

@StevenChurchメールを作成するときの問題はrequest、ドメイン名を取得するオブジェクトがないことだと思います。その場合は、sites代わりにデータベースからドメイン名を取得するフレームワークを使用する必要があります。参照してください。django-absoluteuriこれは、PyPIパッケージのREADMEの「も参照」の項で述べたように、。
Flimm

8

テンプレートから別のページへの完全なリンクを作成するには、これを使用できます。

{{ request.META.HTTP_HOST }}{% url 'views.my_view' my_arg %}

request.META.HTTP_HOSTはホスト名を提供し、urlは相対名を提供します。次に、テンプレートエンジンはそれらを連結して完全なURLにします。


2
答えにはプロトコル(httpこのコンテキストでは)と://URLの一部が欠落しているため、完全なURLは提供されません。
user272735 2015年

2
リクエストオブジェクトにはホストがあります。直接メタを調査しないでください。docs.djangoproject.com/en/1.8/ref/request-response/...
キットSundeの

8

さらに別の方法。で使用build_absolute_uri()してview.py、テンプレートに渡すことができます。

view.py

def index(request):
    baseurl = request.build_absolute_uri()
    return render_to_response('your-template.html', { 'baseurl': baseurl })

your-template.html

{{ baseurl }}

HttpRequest.build_absolute_uri(request)と同等request.build_absolute_uri()ですよね?
mpen 2015年


7

次のコードを試してください:

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

それはパスとクエリ文字列なしでドメインを与えるだけですよね?
mpen

6

これは私のテンプレートで私のために働きました:

{{ request.scheme }}:{{ request.META.HTTP_HOST }}{% url  'equipos:marca_filter' %}

それをjsフェッチ関数に渡すために完全なURLが必要でした。これがお役に立てば幸いです。


5

私はこれが古い質問であることを知っています。しかし、私はまだ多くの人がこれに遭遇すると思います。

デフォルトのDjango機能を補足するライブラリがいくつかあります。私はいくつか試しました。絶対URLを逆参照するときは、次のライブラリが好きです。

https://github.com/fusionbox/django-absoluteuri

ドメイン、プロトコル、パスを簡単にまとめることができるので、もう1つ私が気に入っています。

https://github.com/RRMoelker/django-full-url

このライブラリを使用すると、テンプレートに必要なものを簡単に記述できます。例:

{{url_parts.domain}}

4

django RESTフレームワークを使用している場合は、からリバース関数を使用できますrest_framework.reverse。これは、django.core.urlresolvers.reverseリクエストパラメータを使用して完全なURLを作成することを除いて、と同じ動作です。

from rest_framework.reverse import reverse

# returns the full url
url = reverse('view_name', args=(obj.pk,), request=request)

# returns only the relative url
url = reverse('view_name', args=(obj.pk,))

RESTフレームワークのみでの可用性について言及するように編集されました


を使用してエラーが発生しrequest=requestます。リクエストがここに記載されているようにも見えませんdocs.djangoproject.com/en/1.9/ref/urlresolvers/#reverse
Ryan Amos

これは、RESTフレームワークを使用している場合にのみ利用できることを忘れていました。良いキャッチ、私は私の答えを更新しました。
JohnG、2016年

はいありがとう-と魔法のように、この作品ジャンゴRESTフレームワーク
Apoorv Kansal

1

わかった:

wsgiref.util.request_uri(request.META)

スキーマ、ホスト、ポートパス、クエリを含む完全なURIを取得します。


0

設定として利用可能なABSOLUTE_URL_OVERRIDESもあります

https://docs.djangoproject.com/en/2.1/ref/settings/#absolute-url-overrides

しかし、それはget_absolute_url()をオーバーライドするため、望ましくない場合があります。

このためだけにサイトフレームワークをインストールしたり、ここで説明したリクエストオブジェクトに依存するその他のことを行う代わりに、models.pyに配置することをお勧めします。

BASE_URLをsettings.pyで定義し、models.pyにインポートして、get_truly_absolute_url()を定義する抽象クラスを作成します(またはすでに使用しているクラスに追加します)。それは次のように簡単かもしれません:

def get_truly_absolute_url(self):
    return BASE_URL + self.get_absolute_url()

それをサブクラス化すれば、どこでも使用できます。


0

他の回答で述べたように、にrequest.build_absolute_uri()アクセスできれば完璧です。異なるURLが異なるデータベースを指す限りrequestsitesフレームワークは素晴らしいです。

ただし、使用例は少し異なりました。ステージングサーバーと運用サーバーは同じデータベースにアクセスしましたが、get_current_siteどちらもデータベースの最初のサーバーを返しsiteました。これを解決するには、何らかの環境変数を使用する必要があります。1)環境変数(などos.environ.get('SITE_URL', 'localhost:8000'))または2)SITE_IDサーバーごとに異なると異なるsettings.pyを使用できます

うまくいけば、誰かがこれを便利にするでしょう!


0

成功ページの絶対URIを作成しようとしていたため、このスレッドに出くわしました。request.build_absolute_uri()私の現在のビューのURIを取得しましたが、私の成功ビューのURIを取得するために、以下を使用しました。

request.build_absolute_uri(reverse( 'success_view_name'))



-5

次のものも使用できます。

import socket
socket.gethostname()

これは私にとってはうまく機能しています

私はそれがどのように機能するか完全にはわかりません。これはもう少し低レベルであり、サーバーのホスト名を返すと思います。これは、ユーザーがページにアクセスするために使用するホスト名とは異なる場合があります。


ええ..あなたは問題を指摘しました ホスト名は必ずしもドメイン名と同じである必要はありません。
mpen

これは非常に異なる問題を解決します。複数のWebサイトを持つ共有ホスティングサーバーを検討してください。上記のコードを使用すると、URLを生成するすべてのサイトに、実行中のWebサイトではなく、ホストマシンを指すURLがすべて含まれます。
tbm

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.