¿Cómo obtengo la IP del usuario en django?
Tengo una vista como esta:
# 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())
Pero me sale este error:
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
Respuestas:
Asegúrese de tener el proxy inverso (si lo hay) configurado correctamente (por ejemplo,
mod_rpaf
instalado para Apache).Nota: lo anterior utiliza el primer elemento
X-Forwarded-For
, pero es posible que desee utilizar el último elemento (por ejemplo, en el caso de Heroku: Obtenga la dirección IP real del cliente en Heroku )Y luego simplemente pasa la solicitud como argumento;
fuente
ip = get_client_ip(request)
en su función de vista.X-Forwarded-For: client, proxy1, proxy2
. Entonces, la primera dirección es la del cliente.Puede usar django-ipware que admite Python 2 y 3 y maneja IPv4 e IPv6 .
Instalar en pc:
pip install django-ipware
Uso simple:
Uso avanzado:
Encabezado personalizado: encabezado de solicitud personalizado para que ipware lo vea:
Recuento de proxy: el servidor de Django está detrás de un número fijo de servidores proxy:
Proxies de confianza: el servidor de Django está detrás de uno o más proxies conocidos y de confianza:
Nota: lea este aviso .
fuente
IPWARE_META_PRECEDENCE_LIST
la variable que usa, o use una alternativa como pypi.python.org/pypi/WsgiUnproxyget_client_ip()
.get_real_ip
está en desuso y se eliminará en 3.0.La respuesta de Alexander es excelente, pero carece del manejo de proxies que a veces devuelven múltiples IP en el encabezado HTTP_X_FORWARDED_FOR.
La IP real suele estar al final de la lista, como se explica aquí: http://en.wikipedia.org/wiki/X-Forwards-For
La solución es una simple modificación del código de Alexander:
fuente
request.META
, incluyo un valor predeterminado ya que los encabezados a menudo fallan:request.META.get('REMOTE_ADDR', None)
Me gustaría sugerir una mejora a la respuesta de yanchenko.
En lugar de tomar la primera ip en la lista X_FORWARDED_FOR, tomo la primera que no es una ip interna conocida, ya que algunos enrutadores no respetan el protocolo, y puede ver ips internos como el primer valor de la lista.
Espero que esto ayude a los compañeros de Google que tienen el mismo problema.
fuente
Aquí hay un breve resumen para lograr esto:
fuente
La solución más simple (en caso de que esté usando fastcgi + nignx) es lo que itgorilla comentó:
Ps: agregué esta respuesta solo para hacer que su solución sea más visible.
fuente
proxy_set_header REMOTE_ADDR $remote_addr;
no alivia el problema cuando se agrega a nginx.conf.No más confusión En las versiones recientes de Django se menciona claramente que la dirección IP del cliente está disponible en
Para obtener más información, consulte los documentos de Django
fuente
En mi caso, ninguno de los anteriores funciona, así que tengo que verificar
uwsgi
+django
código fuente y pasar el parámetro estático en nginx y ver por qué / cómo, y a continuación es lo que he encontrado.Información de env:
versión de python : versión de
2.7.5
Django:
(1, 6, 6, 'final', 0)
versión de nginx:
nginx/1.6.0
uwsgi:
2.0.7
Información de configuración de env:
nginx como proxy inverso que escucha en el puerto
80
uwsgi como socket de unix ascendente, eventualmente responderá a la solicitudInformación de configuración de Django:
nginx config:
obteniendo todos los params en la aplicación django:
Conclusión:
Básicamente, debe especificar exactamente el mismo campo / nombre de parámetro en nginx y usarlo
request.META[field/param]
en la aplicación django.Y ahora puede decidir si agregar un middleware (interceptor) o simplemente analizar
HTTP_X_FORWARDED_FOR
en ciertas vistas.fuente
La razón por la que la funcionalidad se eliminó de Django originalmente fue que el encabezado no es confiable. La razón es que es fácil de engañar. Por ejemplo, la forma recomendada de configurar un proxy inverso nginx es:
Cuando tu lo hagas:
Su nginx en myhost.com enviará en adelante:
los
X-Real-IP
será el IP de la primera representación anterior si se siguen las instrucciones ciegamente.En caso de que confiar en quiénes son sus usuarios sea un problema, puede intentar algo como
django-xff
: https://pypi.python.org/pypi/django-xff/fuente
También me faltaba proxy en la respuesta anterior. Solía
get_ip_address_from_request
de django_easy_timezones .Y aquí está el método
get_ip_address_from_request
, IPv4 e IPv6 listo:fuente
En django.VERSION (2, 1, 1, 'final', 0) manejador de solicitudes
si llama dos veces al código anterior, puede obtener
AttributeError ("'_ io.BytesIO' el objeto no tiene atributo 'stream'",)
AttributeError ("el objeto 'LimitedStream' no tiene el atributo 'raw'")
fuente