578👍
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
Make sure you have reverse proxy (if any) configured correctly (e.g. mod_rpaf
installed for Apache).
Note: the above uses the first item in X-Forwarded-For
, but you might want to use the last item (e.g., in the case of Heroku: Get client's real IP address on Heroku)
And then just pass the request as argument to it;
get_client_ip(request)
265👍
You can use django-ipware which supports Python 2 & 3 and handles IPv4 & IPv6.
Install:
pip install django-ipware
Simple Usage:
# In a view or a middleware where the `request` object is available
from ipware import get_client_ip
ip, is_routable = get_client_ip(request)
if ip is None:
# Unable to get the client's IP address
else:
# We got the client's IP address
if is_routable:
# The client's IP address is publicly routable on the Internet
else:
# The client's IP address is private
# Order of precedence is (Public, Private, Loopback, None)
Advanced Usage:
-
Custom Header – Custom request header for ipware to look at:
i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR']) i, r = get_client_ip(request, request_header_order=['X_FORWARDED_FOR', 'REMOTE_ADDR'])
-
Proxy Count – Django server is behind a fixed number of proxies:
i, r = get_client_ip(request, proxy_count=1)
-
Trusted Proxies – Django server is behind one or more known & trusted proxies:
i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2')) # For multiple proxies, simply add them to the list i, r = get_client_ip(request, proxy_trusted_ips=('177.2.2.2', '177.3.3.3')) # For proxies with fixed sub-domain and dynamic IP addresses, use partial pattern i, r = get_client_ip(request, proxy_trusted_ips=('177.2.', '177.3.'))
Note: read this notice.
- [Django]-How to query as GROUP BY in Django?
- [Django]-Django staticfiles not found on Heroku (with whitenoise)
- [Django]-How do you configure Django to send mail through Postfix?
95👍
Alexander’s answer is great, but lacks the handling of proxies that sometimes return multiple IP’s in the HTTP_X_FORWARDED_FOR header.
The real IP is usually at the end of the list, as explained here: http://en.wikipedia.org/wiki/X-Forwarded-For
The solution is a simple modification of Alexander’s code:
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
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-Django create userprofile if does not exist
- [Django]-How to produce a 303 Http Response in Django?
29👍
No More confusion In the recent versions of Django it is mentioned clearly that
the Ip address of the client is available at
request.META.get("REMOTE_ADDR")
for more info check the Django Docs
- [Django]-How to get an ImageField URL within a template?
- [Django]-How to show processing animation / spinner during ajax request?
- [Django]-Explicitly set MySQL table storage engine using South and Django
19👍
I would like to suggest an improvement to yanchenko’s answer.
Instead of taking the first ip in the X_FORWARDED_FOR list, I take the first one which in not a known internal ip, as some routers don’t respect the protocol, and you can see internal ips as the first value of the list.
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
I hope this helps fellow Googlers who have the same problem.
- [Django]-Allowing only super user login
- [Django]-Django count RawQuerySet
- [Django]-How do I use django rest framework to send a file in response?
13👍
here is a short one liner to accomplish this:
request.META.get('HTTP_X_FORWARDED_FOR', request.META.get('REMOTE_ADDR', '')).split(',')[0].strip()
- [Django]-Django rest framework: query parameters in detail_route
- [Django]-What's the idiomatic Python equivalent to Django's 'regroup' template tag?
- [Django]-Django-allauth: Linking multiple social accounts to a single user
7👍
The simpliest solution (in case you are using fastcgi+nignx) is what itgorilla commented:
Thank you for this great question. My fastcgi was not passing the REMOTE_ADDR meta key. I added the line below in the nginx.conf and fixed the problem: fastcgi_param REMOTE_ADDR $remote_addr; – itgorilla
Ps: I added this answer just to make his solution more visible.
- [Django]-Django CMS fails to synch db or migrate
- [Django]-Why there are two process when i run python manage.py runserver
- [Django]-Django aggregate or annotate
7👍
In my case none of above works, so I have to check uwsgi
+ django
source code and pass static param in nginx and see why/how, and below is what I have found.
Env info:
python version: 2.7.5
Django version: (1, 6, 6, 'final', 0)
nginx version: nginx/1.6.0
uwsgi: 2.0.7
Env setting info:
nginx as reverse proxy listening at port 80
uwsgi as upstream unix socket, will response to the request eventually
Django config info:
USE_X_FORWARDED_HOST = True # with or without this line does not matter
nginx config:
uwsgi_param X-Real-IP $remote_addr;
// uwsgi_param X-Forwarded-For $proxy_add_x_forwarded_for;
// uwsgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
// hardcode for testing
uwsgi_param X-Forwarded-For "10.10.10.10";
uwsgi_param HTTP_X_FORWARDED_FOR "20.20.20.20";
getting all the params in django app:
X-Forwarded-For : 10.10.10.10
HTTP_X_FORWARDED_FOR : 20.20.20.20
Conclusion:
So basically, you have to specify exactly the same field/param name in nginx, and use request.META[field/param]
in django app.
And now you can decide whether to add a middleware (interceptor) or just parse HTTP_X_FORWARDED_FOR
in certain views.
- [Django]-Sending an SMS to a Cellphone using Django
- [Django]-Django form fails validation on a unique field
- [Django]-How to define two fields "unique" as couple
4👍
The reason the functionality was removed from Django originally was that the header cannot ultimately be trusted. The reason is that it is easy to spoof. For example the recommended way to configure an Nginx reverse proxy is to:
add_header X-Forwarded-For $proxy_add_x_forwarded_for;
add_header X-Real-Ip $remote_addr;
When you do:
curl -H 'X-Forwarded-For: 8.8.8.8, 192.168.1.2' http://192.168.1.3/
Your Nginx in myhost.example
will send onwards:
X-Forwarded-For: 8.8.8.8, 192.168.1.2, 192.168.1.3
The X-Real-IP
will be the IP of the first previous proxy if you follow the instructions blindly.
In case trusting who your users are is an issue, you could try something like django-xff
: https://pypi.python.org/pypi/django-xff/
- [Django]-Django: Grab a set of objects from ID list (and sort by timestamp)
- [Django]-Filtering using viewsets in django rest framework
- [Django]-Django: Implementing a Form within a generic DetailView
3👍
I was also missing proxy in above answer. I used get_ip_address_from_request
from django_easy_timezones.
from easy_timezones.utils import get_ip_address_from_request, is_valid_ip, is_local_ip
ip = get_ip_address_from_request(request)
try:
if is_valid_ip(ip):
geoip_record = IpRange.objects.by_ip(ip)
except IpRange.DoesNotExist:
return None
And here is method get_ip_address_from_request
, IPv4 and IPv6 ready:
def get_ip_address_from_request(request):
""" Makes the best attempt to get the client's real IP or return the loopback """
PRIVATE_IPS_PREFIX = ('10.', '172.', '192.', '127.')
ip_address = ''
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR', '')
if x_forwarded_for and ',' not in x_forwarded_for:
if not x_forwarded_for.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_forwarded_for):
ip_address = x_forwarded_for.strip()
else:
ips = [ip.strip() for ip in x_forwarded_for.split(',')]
for ip in ips:
if ip.startswith(PRIVATE_IPS_PREFIX):
continue
elif not is_valid_ip(ip):
continue
else:
ip_address = ip
break
if not ip_address:
x_real_ip = request.META.get('HTTP_X_REAL_IP', '')
if x_real_ip:
if not x_real_ip.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(x_real_ip):
ip_address = x_real_ip.strip()
if not ip_address:
remote_addr = request.META.get('REMOTE_ADDR', '')
if remote_addr:
if not remote_addr.startswith(PRIVATE_IPS_PREFIX) and is_valid_ip(remote_addr):
ip_address = remote_addr.strip()
if not ip_address:
ip_address = '127.0.0.1'
return ip_address
- [Django]-Django manage.py runserver invalid syntax
- [Django]-Paginating the results of a Django forms POST request
- [Django]-Django index page best/most common practice
1👍
In django.VERSION
(2, 1, 1, ‘final’, 0)
request handler
sock=request._stream.stream.raw._sock
#<socket.socket fd=1236, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('192.168.1.111', 8000), raddr=('192.168.1.111', 64725)>
client_ip,port=sock.getpeername()
if you call above code twice,you may got
AttributeError(“‘_io.BytesIO’ object has no attribute ‘stream'”,)
AttributeError(“‘LimitedStream’ object has no attribute ‘raw'”)
- [Django]-How do I install psycopg2 for Python 3.x?
- [Django]-How to access Enum types in Django templates
- [Django]-Django admin and MongoDB, possible at all?
1👍
Simply add
{{ request.META.REMOTE_ADDR }}
In Django-Template where you want the user to see their IP address. That is if you are not interested in saving this to the DB.
- [Django]-Stack trace from manage.py runserver not appearing
- [Django]-Suddenly when running tests I get "TypeError: 'NoneType' object is not iterable
- [Django]-No module named MySQLdb
1👍
Get the ip address with this function:
def get_ip_address(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
after that you can get the user location data and other info from that web app http://www.iplocinfo.com/:
import requests
def get_ip_data(request):
ip_address = get_ip_address(request)
api_key = "your api key"
endPoint = f'https://www.iplocinfo.com/api/v1/{ip_address}?apiKey={api_key}'
data = requests.get(endPoint)
return data.json()
- [Django]-Create custom buttons in admin change_form in Django
- [Django]-Django: Multiple forms possible when using FormView?
- [Django]-How does django handle multiple memcached servers?
0👍
After getting ip address you need to find location
# pip install geocoder
import geocoder
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]
ip_location = geocoder.ip(f"{ip}")
ip_location = geocoder.ip("me")
print(ip_location.city)
# you can get city such as "New York"
else:
ip = request.META.get('REMOTE_ADDR')
return ip
- [Django]-In a Django form, how do I make a field readonly (or disabled) so that it cannot be edited?
- [Django]-Django – Annotate multiple fields from a Subquery
- [Django]-How to check if ManyToMany field is not empty?
0👍
In the folder where manage.py is located I created a file named getIP with the folowing code:
import socket
def getip():
hostname = socket.gethostname()
ipddr = socket.gethostbyname(hostname)
print("HOSTNAME:"+hostname)
print("IP:"+ipddr)
return f'{ipddr}'
in manage.py I did some modifications as following (Python 3.9 and Django 4.2.7):
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
from getIP import getip
from django.core.management.commands.runserver import Command as Crs
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MyApp.settings')
try:
from django.core.management import execute_from_command_line
Crs.default_addr = getip()
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
in windows prompt command the output is:
(venv) C:\MyProject\MyApp>python manage.py runserver
HOSTNAME:DESKTOP-xxxxxx
IP:192.168.XX.XX
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
December 08, 2023 - 10:26:31
Django version 4.2.7, using settings 'MyApp.settings'
Starting development server at http://192.168.XX.XX:8000/
Quit the server with CTRL-BREAK.
- [Django]-Timestamp fields in django
- [Django]-In django, how do I sort a model on a field and then get the last item?
- [Django]-Django + Ajax