399 votes

Comment puis-je obtenir l'adresse IP de l'utilisateur dans Django?

Comment puis-je obtenir l'adresse IP de l'utilisateur dans Django?

J'ai une vue comme celle-ci:

 # Create your views
from django.contrib.gis.utils import GeoIP
from django.template import  RequestContext
from django.shortcuts import render_to_response


def home(request):
  g = GeoIP()
  client_ip = request.META['REMOTE_ADDR']
  lat,long = g.lat_lon(client_ip)
  return render_to_response('home_page_tmp.html',locals())
 

Mais j'ai cette erreur:

 KeyError at /mypage/
    'REMOTE_ADDR'
    Request Method: GET
    Request URL:    http://mywebsite.com/mypage/
    Django Version: 1.2.4
    Exception Type: KeyError
    Exception Value:    
    'REMOTE_ADDR'
    Exception Location: /mysite/homepage/views.py in home, line 9
    Python Executable:  /usr/bin/python
    Python Version: 2.6.6
    Python Path:    ['/mysite', '/usr/local/lib/python2.6/dist-packages/flup-1.0.2-py2.6.egg', '/usr/lib/python2.6', '/usr/lib/python2.6/plat-linux2', '/usr/lib/python2.6/lib-tk', '/usr/lib/python2.6/lib-old', '/usr/lib/python2.6/lib-dynload', '/usr/local/lib/python2.6/dist-packages', '/usr/lib/python2.6/dist-packages', '/usr/lib/pymodules/python2.6']
    Server time:    Sun, 2 Jan 2011 20:42:50 -0600
 

591voto

yanchenko Points 24142
 def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip
 

Assurez-vous que le proxy inverse (le cas échéant) est configuré correctement (par exemple, mod_rpaf installé pour Apache).

271voto

Val Neekman Points 1238

Vous pouvez rester au SEC et il suffit d'utiliser django-ipware qui prend en charge à la fois IPv4 et IPv6 ainsi que Python 3.

Installer:

pip install django-ipware

De votre point de vue ou middleware:

from ipware.ip import get_ip
ip = get_ip(request)
if ip is not None:
    print "we have an IP address for user"
else:
    print "we don't have an IP address for user"

Il fera au mieux tenter d'obtenir l'adresse IP de l'utilisateur ou les retours None à indiquer qu'il n'a pas pu déterminer l'adresse IP de l'utilisateur.

96voto

Sævar Points 820

La réponse d'Alexander est géniale, mais il lui manque le traitement des proxy qui renvoient parfois plusieurs adresses IP dans l'en-tête HTTP_X_FORWARDED_FOR.

La vraie IP est généralement à la fin de la liste, comme expliqué ici: http://en.wikipedia.org/wiki/X-Forwarded-For

La solution est une simple modification du code d'Alexander:

 def get_client_ip(request):
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[-1].strip()
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip
 

19voto

Doody P Points 82

Je voudrais suggérer une amélioration à la réponse de Yanchenko.

Au lieu de prendre la première adresse IP dans la liste X_FORWARDED_FOR, je prends la première qui n'est pas une adresse IP interne connue, car certains routeurs ne respectent pas le protocole et vous pouvez voir les ips internes comme première valeur de la liste.

 PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', )

def get_client_ip(request):
    """get the client ip from the request
    """
    remote_address = request.META.get('REMOTE_ADDR')
    # set the default value of the ip to be the REMOTE_ADDR if available
    # else None
    ip = remote_address
    # try to get the first non-proxy ip (not a private ip) from the
    # HTTP_X_FORWARDED_FOR
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        proxies = x_forwarded_for.split(',')
        # remove the private ips from the beginning
        while (len(proxies) > 0 and
                proxies[0].startswith(PRIVATE_IPS_PREFIX)):
            proxies.pop(0)
        # take the first ip which is not a private one (of a proxy)
        if len(proxies) > 0:
            ip = proxies[0]

    return ip
 

J'espère que cela aidera les autres Googlers qui ont le même problème.

7voto

Juande Carrion Points 590

La solution la plus simple (dans le cas où vous utilisez fastcgi + nignx) est ce que itgorilla a commenté:

Merci pour cette excellente question. Mon fastcgi ne transmettait pas la clé méta REMOTE_ADDR. J'ai ajouté la ligne ci-dessous dans le fichier nginx.conf et résolu le problème: fastcgi_param REMOTE_ADDR $ remote_addr; - Itgorilla

Ps: J'ai ajouté cette réponse pour rendre sa solution plus visible.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X