web-dev-qa-db-fra.com

Comment puis-je obtenir l'URL complète/absolue (avec le domaine) dans Django?

Comment obtenir l'URL complète/absolue (par exemple https://example.com/some/path) dans Django sans le module Sites ? C'est juste idiot ... Je ne devrais pas avoir besoin d'interroger ma base de données pour accrocher l'URL!

Je veux l'utiliser avec reverse().

317
mpen

Utilisez la méthode request.build_absolute_uri () à la demande, transmettez-lui l'URL relative et vous en aurez une complète.

Par défaut, l'URL absolue de request.get_full_path() est renvoyée, mais vous pouvez lui transmettre une URL relative en tant que premier argument pour le convertir en une URL absolue.

454
Dmitry Shevchenko

Si vous voulez l'utiliser avec reverse(), vous pouvez faire ceci: request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))

73
ébewè

Vous pouvez également utiliser get_current_site dans le cadre de l'application Sites (from Django.contrib.sites.models import get_current_site). Il prend un objet de requête et utilise par défaut l'objet de site que vous avez configuré avec SITE_ID dans settings.py si la requête est None. Plus d'informations dans la documentation pour en utilisant le framework de sites

par exemple.

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

Ce n'est pas aussi compact/net que request.build_absolute_url(), mais il est utilisable lorsque les objets de requête ne sont pas disponibles et vous avez une URL de site par défaut.

48
Darb

Si vous ne pouvez pas accéder à request, vous ne pouvez pas utiliser get_current_site(request) comme recommandé dans certaines solutions ici. Vous pouvez utiliser une combinaison du framework de sites natif et de get_absolute_url à la place. Configurez au moins un Site dans l’administrateur, assurez-vous que votre modèle a une méthode get_absolute_url () , puis:

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

43
shacker

Si vous ne voulez pas accéder à la base de données, vous pouvez le faire avec un paramètre. Ensuite, utilisez un processeur de contexte pour l'ajouter à chaque modèle:

# 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
seddonym

Django-fullurl

Si vous essayez de faire cela dans un modèle Django, j'ai publié un petit paquet PyPI Django-fullurl pour vous permettre de remplacer les balises de modèle url et static par fullurl et fullstatic, comme ceci:

{% load fullurl %}

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

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

Espérons que ces badges restent automatiquement à jour:

 PyPI  Travis CI

Dans une vue, vous pouvez bien sûr utiliser request.build_absolute_uri .

10
Flimm

Pour créer un lien complet vers une autre page à partir d'un modèle, vous pouvez utiliser ceci:

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

request.META.HTTP_Host donne le nom de l'hôte et url le nom relatif. Le moteur de gabarit les concatène ensuite dans une URL complète.

8
Doug Bradshaw

À votre avis, faites ceci:

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

Examiner le dictionnaire Request.META qui entre.

7
Kugel

Encore une autre façon. Vous pouvez utiliser build_absolute_uri() dans votre view.py et le transmettre au modèle.

view.py

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

votre-template.html

{{ baseurl }}
7
Sven Rojek

Essayez le code suivant:

{{ request.scheme }}://{{ request.META.HTTP_Host }}
5
mark

Je sais que c'est une vieille question. Mais je pense que les gens se heurtent encore souvent à cela.

Quelques bibliothèques complètent la fonctionnalité par défaut de Django. J'ai essayé quelques-uns. J'aime la bibliothèque suivante lors du référencement inversé d'URL absolus:

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

Un autre que j’aime bien parce que vous pouvez facilement mettre en place un domaine, un protocole et un chemin est:

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

Cette bibliothèque vous permet d’écrire simplement ce que vous voulez dans votre modèle, par exemple:

{{url_parts.domain}}
5
johniak20

Cela a fonctionné pour moi dans mon modèle:

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

J'avais besoin de l'URL complète pour la transmettre à une fonction d'extraction js. J'espère que cela vous aidera.

2
Jose Luis Quichimbo

Si vous utilisez le framework Django REST, vous pouvez utiliser la fonction inverse de rest_framework.reverse. Cela a le même comportement que Django.core.urlresolvers.reverse, sauf qu'il utilise un paramètre de requête pour créer une URL complète.

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,))

Édité pour mentionner la disponibilité uniquement dans le cadre REST

2
JohnG

J? ai compris:

wsgiref.util.request_uri(request.META)

Obtenez l'URI complet avec schéma, hôte, chemin du port et requête.

1
wonder

ABSOLUTE_URL_OVERRIDES est également disponible en tant que paramètre.

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

Mais cela annule get_absolute_url (), ce qui peut ne pas être souhaitable.

Au lieu d'installer la structure de sites uniquement pour cela ou de faire certaines des choses mentionnées ici qui reposent sur un objet de requête, je pense que la meilleure solution consiste à placer ceci dans models.py 

Définissez BASE_URL dans settings.py, puis importez-le dans models.py et créez une classe abstraite (ou ajoutez-la à celle que vous utilisez déjà) définissant get_truly_absolute_url (). Cela pourrait être aussi simple que:

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

Sous-classe et maintenant vous pouvez l'utiliser partout.

0
aris