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()
.
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.
Si vous voulez l'utiliser avec reverse()
, vous pouvez faire ceci: request.build_absolute_uri(reverse('view_name', args=(obj.pk, )))
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.
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
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>
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:
Dans une vue, vous pouvez bien sûr utiliser request.build_absolute_uri
.
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.
À votre avis, faites ceci:
base_url = "{0}://{1}{2}".format(request.scheme, request.get_Host(), request.path)
Examiner le dictionnaire Request.META
qui entre.
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 }}
Essayez le code suivant:
{{ request.scheme }}://{{ request.META.HTTP_Host }}
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}}
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.
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
J? ai compris:
wsgiref.util.request_uri(request.META)
Obtenez l'URI complet avec schéma, hôte, chemin du port et requête.
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.