2010-11-10 18 views
15

J'ai un modèle comme celui ci-dessous. Lorsqu'une instance est créée, je veux envoyer un e-mail à une partie intéressée:Django: Obtention de l'URL absolue sans accès à un objet de requête

class TrainStop(models.Model): 
    name = models.CharField(max_length=32) 
    notify_email = models.EmailField(null=True, blank=True) 

def new_stop_created(sender, instance, created, *args, **kwargs): 

    # Only for new stops 
    if not created or instance.id is None: return 

    # Send the status link 
    if instance.notify_email: 
     send_mail(
      subject='Stop submitted: %s' % instance.name, 
      message='Check status: %s' % reverse('stop_status', kwargs={'status_id':str(instance.id),}), 
      from_email='[email protected]', 
      recipient_list=[instance.notify_email,] 
     ) 
signals.post_save.connect(new_stop_created, sender=TrainStop) 

Cependant, l'appel reverse retourne uniquement la partie du chemin de l'URL. Exemple: /stops/9/status/. J'ai besoin d'un URL complet comme http://example.com/stops/9/status/. Comment puis-je récupérer le nom d'hôte et le port (pour les instances de test qui n'utilisent pas le port 80) du site Web actuel?

Ma pensée initiale était de rendre cela disponible via une variable en settings.py que je pouvais ensuite accéder au besoin. Cependant, pensé que quelqu'un pourrait avoir une suggestion plus robuste.

Répondre

4

Il y a le cadre de sites, yedpodtrzitko mentionné, mais, comme vous l'avez mentionné, il est très bien une configuration manuelle.

Un paramètre est requis dans settings.py, mais il est légèrement moins manuel que la configuration de sites. (Il peut gérer plusieurs domaines, tout comme les sites et le réglage SITE_ID).

Il y a une idée pour replacing get_absolute_url, qui rendrait ce genre de choses plus facile, même si je pense que son implémentation souffre du même problème (comment obtenir le domaine, le schéma [http vs https], etc.).

Je me suis mis à l'idée d'un intergiciel qui examine les requêtes entrantes et construit un paramètre de "domaine le plus probable" en fonction de la fréquence de la valeur de l'en-tête HTTP HOST. Ou peut-être qu'il pourrait définir ce paramètre sur chaque demande individuellement, de sorte que vous pouvez toujours avoir le domaine en cours de travailler avec. Je ne suis pas allé au point d'y regarder sérieusement, mais c'est une pensée.

+0

"S'ils ne prennent pas la peine de le configurer, mon application ne prendra pas la peine de travailler pour eux", mais cela n'est pas utile "Comment pouvez-vous appeler en disant" une exigence "pour être" pas utile "? Il faut mettre dans les paramètres et c'est la fin de cela.La plus grande partie de Django nécessite des paramètres ou cela ne fonctionne pas.Pourquoi cette application doit être "magique" et ne nécessite pas de paramètres? Si vous ne pouvez pas compter sur l'utilisateur, alors, ils vont faire quelque chose d'autre pour subvertir l'application aussi, ne sont-ils pas? Comme modifier le code.Indiquez simplement les paramètres requis et faites-le avec. Ne pas gaufres. –

+0

Cela est vrai, mais je voulais dire plus que cela n'est pas utile à notre discussion actuelle vers une méthode de détection de domaine fiable. Vous avez raison, cependant, c'est stupide de ma part de dire que nous ne pouvons pas compter sur l'utilisateur comme ça. – eternicode

+0

Vous ne pouvez pas détecter le domaine sans la demande, et 'reverse' ou' {% url%} '. Tout le reste ** nécessite ** un paramètre. C'est simple. Pas de raison de s'en plaindre. Exiger le réglage et être fait. –

4

Pour obtenir site actuel il y a objet du site:

Si vous ne disposez pas d'accès à l'objet de la demande, vous pouvez utiliser la méthode get_current() du gestionnaire du modèle du site. Vous devez alors vérifier que votre fichier de paramètres contient le paramètre SITE_ID. Ce exemple est équivalent à la précédente:

from django.contrib.sites.models import Site 

def my_function_without_request(): 
    current_site = Site.objects.get_current() 
    if current_site.domain == 'foo.com': 
     # Do something 
     pass 
    else: 
     # Do something else. 
     pass 

Plus d'info: http://docs.djangoproject.com/en/dev/ref/contrib/sites/

+0

Je n'utilise pas actuellement le framework de sites. Il semble que ce sera plus de travail que ce que ça vaut juste pour obtenir le domaine actuel - qui doit être configuré manuellement de toute façon. Merci quand même. –

+0

Je suis confus. C'est précisément ce à quoi sert le cadre des sites, et cela vous donne la possibilité de définir cette information une fois et de la rendre disponible partout. Il est également beaucoup plus facile à modifier lorsqu'il se trouve dans la base de données que, comme vous l'avez suggéré, dans le fichier de paramètres. Alors, quel est exactement le problème? –

+2

A partir de la documentation des sites: "Utilisez-la si votre seule installation Django gère plus d'un site et que vous devez différencier ces sites d'une manière ou d'une autre". Ce n'est pas un projet avec plusieurs sites Web, donc imho, la mise en œuvre d'un modèle pour stocker ces données est trop pour ma situation. –