मैं एक Django टेम्पलेट के भीतर अपनी साइट का डोमेन नाम कैसे प्राप्त कर सकता हूं?


156

मुझे Django टेम्पलेट के भीतर से अपनी वर्तमान साइट का डोमेन नाम कैसे मिलेगा? मैंने टैग और फ़िल्टर में देखने की कोशिश की है, लेकिन वहां कुछ भी नहीं है।

जवाबों:


67

मुझे लगता है कि आप जो चाहते हैं वह अनुरोध संदर्भ के लिए उपयोग करना है, RequestContext देखें।


140
request.META['HTTP_HOST']आपको डोमेन देता है। एक टेम्पलेट में यह होगा {{ request.META.HTTP_HOST }}
डैनियल रोसमैन

29
अनुरोध मेटाडेटा का उपयोग करने के साथ सावधान रहें। यह एक ब्राउज़र से आ रहा है और इसे स्पूफ किया जा सकता है। सामान्य तौर पर, आप शायद @CarlMeyer द्वारा नीचे दिए गए सुझाव के साथ जाना चाहेंगे।
जोश

2
मेरे उद्देश्यों के लिए, इसमें कोई सुरक्षा छेद नहीं है।
पॉल ड्रेपर

7
मुझे लगता है, जब से Django 1.5 की अनुमति देता है मेजबानों की स्थापना के साथ यह उपयोग करने के लिए सुरक्षित है। docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
डैनियल बैकमैन

8
क्या कोई "सुरक्षा छेद" के बारे में विस्तार से बता सकता है? यदि उपयोगकर्ता Host:हेडर को खराब कर देता है और किसी पृष्ठ पर स्पूफ किए गए डोमेन के साथ प्रतिक्रिया प्राप्त करता है, तो वह सुरक्षा छेद कैसे बनाता है? मैं यह नहीं देखता कि जेनरेट किए गए HTML को लेने वाले उपयोगकर्ता से कैसे भिन्न होता है और इसे अपने ब्राउज़र में फीड करने से पहले खुद को संशोधित करता है।
user193130

105

यदि आप वास्तविक HTTP होस्ट हेडर चाहते हैं, तो @ Phsiao के उत्तर पर डैनियल रोजमैन की टिप्पणी देखें। दूसरा विकल्प अगर आप कंट्रिब.साइट्स फ्रेमवर्क का उपयोग कर रहे हैं , तो आप डेटाबेस में किसी साइट के लिए एक कैनोनिकल डोमेन नाम सेट कर सकते हैं (अनुरोध डोमेन को उचित SITE_ID के साथ सेटिंग फ़ाइल में मैप करना कुछ ऐसा है जिसे आपको अपने आप से करना होगा वेबसर्वर सेटअप)। उस मामले में आप देख रहे हैं:

from django.contrib.sites.models import Site

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

यदि आप इसका उपयोग करना चाहते हैं, तो आपको करंट संदर्भ में current_site ऑब्जेक्ट को स्वयं डालना होगा। यदि आप इसे पूरे स्थान पर उपयोग कर रहे हैं, तो आप एक टेम्पलेट संदर्भ प्रोसेसर में पैकेज कर सकते हैं।


3
किसी ऐसे व्यक्ति के लिए स्पष्ट करने के लिए जो मेरे पास समान समस्याएं हैं: जांचें कि आपकी SITE_IDसेटिंग idसाइट एप्लिकेशन की वर्तमान साइट की विशेषता के बराबर है (आप idसाइट व्यवस्थापक पैनल में पा सकते हैं )। जब आप कॉल करते हैं get_current, तो Django आपका लेता है SITE_IDऔर Siteडेटाबेस से उस आईडी के साथ ऑब्जेक्ट लौटाता है ।
डेनिस गोलोमेज़ोव

इनमें से कोई भी मेरे लिए काम नहीं करता है। 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
कृपया ध्यान दें कि इस उत्तर में डैनियल रोज़मैन दृष्टिकोण के समान मुद्दे हैं (इसे खराब किया जा सकता है) लेकिन यह निश्चित रूप से अधिक पूर्ण होता है जब होस्ट HTTP प्रॉक्सी या लोड बैलेंसर के माध्यम से पहुंचता है क्योंकि यह HTTP_X_FORWARDED_HOSTHTTP हेडर के खाते में ले जाता है ।
फरेंस

4
उपयोग: "// {{request.get_host}} / कुछ / और / आप / चाहते हैं ... ... अपनी ALLOWED_HOSTS सेटिंग ( docs.djangoproject.com/en/1.5/ref/slings/#allowed देखें) भरना सुनिश्चित करें -हो्स )।
सेठ

3
@ बेहतर उपयोग करने के लिए request.build_absolute_uri( docs.djangoproject.com/en/dev/ref/request-response/… )
Mrssn

60

कार्ल मेयर को लागू करते हुए, आप इस तरह एक संदर्भ प्रोसेसर बना सकते हैं:

module.context_processors.py

from django.conf import settings

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

स्थानीय सेटिंग्स

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}}

यदि आप संदर्भ प्रोसेसर में सबडोमेन या एसएसएल को हैंडल करना चाहते हैं, तो अपनी खुद की रूटीन लिख सकते हैं।


मैंने इस समाधान की कोशिश की, लेकिन अगर आपके पास एक ही एप्लिकेशन के लिए कई उप-डोमेन हैं, तो यह व्यावहारिक नहीं है, मुझे डैनब्रुएज द्वारा जवाब बहुत उपयोगी लगा
जोस लुइस डे ला रोजा

settings.py में आपको अपने संदर्भ प्रोसेसर को
संदर्भ_प्रोसेसर

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आवरण यकीन है कि डीबी कॉल केवल तब होता है जब टेम्पलेट वास्तव में उपयोग करता है बनाता है 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यहां उपयोग करने की आवश्यकता नहीं है, क्योंकि लैंबडा अभ्यस्त होने पर भी कुछ भी नहीं कहा जा सकता है।
मोनोक्रोम

यदि आप हटाते हैं SimpleLazyObject, तो प्रत्येक RequestContextकॉल करेगा get_current_site(), और इसलिए SQL क्वेरी निष्पादित करेगा । आवरण सुनिश्चित करता है कि चर का मूल्यांकन केवल तब किया जाता है जब वह वास्तव में टेम्पलेट में उपयोग किया जाता है।
vdboor

1
चूंकि यह एक फंक्शन है, होस्ट स्ट्रिंग को तब तक संसाधित नहीं किया जाएगा जब तक कि इसे किसी भी तरह से उपयोग नहीं किया जाता है। इसलिए, आप केवल 'site_root' पर एक फ़ंक्शन असाइन कर सकते हैं और आपको SimpleLazyObject की आवश्यकता नहीं है। Django फ़ंक्शन को कॉल करेगा जब इसका उपयोग किया जाएगा। आप पहले से ही यहाँ एक मेमने के साथ आवश्यक कार्य बना चुके हैं।
मोनोक्रोम

आह हाँ, केवल एक भेड़ का बच्चा काम करेगा। 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यहाँ प्रलेखित है
फिलिप ज़ेडलर

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 }}

यदि आप रेंडर का उपयोग कर रहे हैं, तो एक RequestContext का उपयोग करना सुनिश्चित करें ।

request.META['HTTP_HOST']उत्पादन पर भरोसा न करें : यह जानकारी ब्राउज़र से आती है। इसके बजाय, @ कार्लमेयर के उत्तर का उपयोग करें


मैं इस उत्तर को बढ़ा रहा हूं लेकिन जब उपयोग करने का प्रयास किया गया तो मुझे एक त्रुटि मिली request.scheme। शायद केवल django के नए संस्करणों में उपलब्ध है।
मैट क्रीमन्स

@MattCremeens request.schemeको Django 1.7 में जोड़ा गया था।
एस किर्बी

16

{{ request.get_host }}जब ALLOWED_HOSTSसेटिंग (Django 1.4.4 में जोड़ा) के साथ प्रयोग किया जाता है HTTP होस्ट हेडर हमलों के खिलाफ की रक्षा करनी चाहिए ।

ध्यान दें कि {{ request.META.HTTP_HOST }}समान सुरक्षा नहीं है। डॉक्स देखें :

ALLOWED_HOSTS

होस्ट / डोमेन नामों का प्रतिनिधित्व करने वाले स्ट्रिंग्स की एक सूची जो इस Django साइट की सेवा कर सकती है। यह 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 %}

क्या इस दृष्टिकोण के लिए कोई विशेष नकारात्मक पक्ष है? साइट के लिए कॉल के अलावा हर अनुरोध पर डीबी।
किकर

@ Kicker86 मैं किसी को नहीं जानता। get_currentएक प्रलेखित विधि है: docs.djangoproject.com/en/dev/ref/contrib/sites/…
डेनिस गोलोमेज़ोव

3
'http://%s'httpsकनेक्शन के मामले में समस्या हो सकती है ; इस मामले में योजना गतिशील नहीं है।
ऑर्गेनिक

4

उपयोगकर्ता के पंचकोश के उत्तर के समान, यह वही है जो मैंने एक बहुत ही सरल वेबसाइट पर किया था। यह कुछ चर प्रदान करता है और उन्हें टेम्पलेट पर उपलब्ध कराता है।

SITE_URLकी तरह एक मूल्य पकड़ होगा example.com
SITE_PROTOCOLकी तरह एक मूल्य पकड़ होगा http या https
SITE_PROTOCOL_URLकी तरह एक मूल्य पकड़ होगा http://example.comया https://example.com
SITE_PROTOCOL_RELATIVE_URLकी तरह एक मूल्य पकड़ होगा //example.com

मॉड्यूल / 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 डेवलपर्स के लिए एक महान स्रोत है! :)
डॉस

2

यदि आप "अनुरोध" संदर्भ प्रोसेसर का उपयोग करते हैं, और Django साइटों के ढांचे का उपयोग कर रहे हैं , और साइट मिडलवेयर स्थापित है (यानी आपकी सेटिंग्स शामिल हैं):

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)

लेकिन इसके साथ प्रयास localhostकरने पर आपको एक httpsस्कीम मिल जाएगी (इसे सुरक्षित माना जाता है) जो तब काम नहीं करेगी जब आपको स्टैटिक यूआरएल मिल गया हो (केवल http://127.0.0.1मान्य है, नहीं https://127.0.0.1)। तो यह आदर्श नहीं है जब अभी भी विकास में है।
thePhi


-5

आप {{ protocol }}://{{ domain }}अपने डोमेन नाम प्राप्त करने के लिए अपने टेम्पलेट में उपयोग कर सकते हैं ।


मुझे नहीं लगता कि @ इरान नोटिस करता है कि यह एक गैर-मानक अनुरोध संदर्भ प्रोसेसर पर निर्भर करता है।
मोनोक्रोम

मैं यह काम नहीं कर सका, आप प्रोटोकॉल और डोमेन को कहां परिभाषित करते हैं?
जोस लुइस डी ला रोजा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.